added uninit status; added deferred iv; various related fixes

This commit is contained in:
2021-02-22 10:39:24 -05:00
parent 9be0f5f81b
commit 06974416f3
13 changed files with 95 additions and 52 deletions

View File

@@ -11,11 +11,13 @@ public abstract class AbstractBuffer {
protected long targetBytesWritten = 0L;
protected boolean started = false;
protected boolean finished = false;
protected boolean initialized = false;
public Status getStatus() {
if (this.finished) return Status.Finished;
else if (this.started) return Status.Started;
else return Status.Initialized;
else if (this.initialized) return Status.Initialized;
else return Status.Uninitialized;
}
public long getTotalBytesRead() {

View File

@@ -75,6 +75,8 @@ public class CipherBuffer extends AbstractBuffer {
cipher = cparams.getProvider() == null ? Cipher.getInstance(transformation) : Cipher.getInstance(transformation, cparams.getProvider());
}
this.initialized = true;
if (cparams.getInitializationVector() != null) {
if (this.logger.isDebugEnabled())
this.logger.debug("initializing cipher with specified IV scrambler");
@@ -85,6 +87,10 @@ public class CipherBuffer extends AbstractBuffer {
byte[] iv = new byte[cipher.getBlockSize()];
new SecureRandom().nextBytes(iv);
cipher.init(this.cipherMode, this.key, new IvParameterSpec(iv));
} else if (cparams.isDeferInitializationVector()) {
if (this.logger.isDebugEnabled())
this.logger.debug("delaying cipher initialization ...");
this.initialized = false;
} else {
if (this.logger.isDebugEnabled())
this.logger.debug("initializing cipher without IV scrambler");
@@ -115,6 +121,7 @@ public class CipherBuffer extends AbstractBuffer {
if (this.logger.isDebugEnabled())
this.logger.debug("re-initializing cipher with specified IV scrambler");
this.cipher.init(this.cipherMode, this.key, new IvParameterSpec(initializationVector));
this.initialized = true;
} catch (InvalidKeyException ike) {
throw new RuntimeException("This will never happen; the key was already declared valid by previous init()");
}

View File

@@ -5,53 +5,68 @@ import java.security.Provider;
public class CipherParameters {
public enum IVSource {
None,
Generated,
Deferred,
Provided
}
private int cipherMode;
private Key key;
private String transformation;
private boolean generateInitializationVector = false;
private byte[] initializationVector;
private boolean generateIV = false;
private boolean deferIV = false;
private byte[] iv;
private Provider provider;
public CipherParameters(int cipherMode, Key key) {
this(cipherMode, key, null, null, null);
this(cipherMode, key, null, IVSource.None, null, null);
}
public CipherParameters(int cipherMode, Key key, String transformation) {
this(cipherMode, key, transformation, null, null);
this(cipherMode, key, transformation, IVSource.None, null, null);
}
public CipherParameters(int cipherMode, Key key, String transformation, boolean generateInitializationVector) {
this(cipherMode, key, transformation, new byte[0], null);
public CipherParameters(int cipherMode, Key key, String transformation, IVSource ivSource) {
this(cipherMode, key, transformation, ivSource, null, null);
}
public CipherParameters(int cipherMode, Key key, String transformation, byte[] initializationVector) {
this(cipherMode, key, transformation, initializationVector, null);
this(cipherMode, key, transformation, IVSource.Provided, initializationVector, null);
}
public CipherParameters(int cipherMode, Key key, Provider provider) {
this(cipherMode, key, null, null, provider);
this(cipherMode, key, null, IVSource.None, null, provider);
}
public CipherParameters(int cipherMode, Key key, String transformation, Provider provider) {
this(cipherMode, key, transformation, null, provider);
this(cipherMode, key, transformation, IVSource.None, null, provider);
}
public CipherParameters(int cipherMode, Key key, String transformation, boolean generateInitializationVector, Provider provider) {
this(cipherMode, key, transformation, new byte[0], provider);
public CipherParameters(int cipherMode, Key key, String transformation, IVSource ivSource, Provider provider) {
this(cipherMode, key, transformation, ivSource, null, provider);
}
public CipherParameters(int cipherMode, Key key, String transformation, byte[] initializationVector, Provider provider) {
this(cipherMode, key, transformation, IVSource.Provided, initializationVector, provider);
}
private CipherParameters(int cipherMode, Key key, String transformation, IVSource ivSource, byte[] initializationVector, Provider provider) {
this.cipherMode = cipherMode;
this.key = key;
this.transformation = transformation;
this.provider = provider;
if (initializationVector != null) {
if (initializationVector.length == 0) {
this.generateInitializationVector = true;
} else {
this.initializationVector = initializationVector;
}
switch (ivSource) {
case Generated:
this.generateIV = true;
case Deferred:
this.deferIV = true;
case Provided:
this.iv = initializationVector;
case None:
default:
}
}
@@ -83,20 +98,29 @@ public class CipherParameters {
}
public byte[] getInitializationVector() {
return this.initializationVector;
return this.iv;
}
public CipherParameters setInitializationVector(byte[] initializationVector) {
this.initializationVector = initializationVector;
this.iv = initializationVector;
return this;
}
public boolean isGenerateInitializationVector() {
return this.generateInitializationVector;
return this.generateIV;
}
public CipherParameters setGenerateInitializationVector(boolean generateInitializationVector) {
this.generateInitializationVector = generateInitializationVector;
this.generateIV = generateInitializationVector;
return this;
}
public boolean isDeferInitializationVector() {
return this.deferIV;
}
public CipherParameters setDeferInitializationVector(boolean deferInitializationVector) {
this.deferIV = deferInitializationVector;
return this;
}

View File

@@ -15,6 +15,10 @@ public class DecryptingCipherParameters extends CipherParameters {
super(Cipher.DECRYPT_MODE, key, transformation);
}
public DecryptingCipherParameters(Key key, String transformation, boolean deferInitializationVector) {
super(Cipher.DECRYPT_MODE, key, transformation, deferInitializationVector ? IVSource.Deferred : IVSource.None);
}
public DecryptingCipherParameters(Key key, String transformation, byte[] initializationVector) {
super(Cipher.DECRYPT_MODE, key, transformation, initializationVector);
}
@@ -27,6 +31,10 @@ public class DecryptingCipherParameters extends CipherParameters {
super(Cipher.DECRYPT_MODE, key, transformation, provider);
}
public DecryptingCipherParameters(Key key, String transformation, boolean deferInitializationVector, Provider provider) {
super(Cipher.DECRYPT_MODE, key, transformation, deferInitializationVector ? IVSource.Deferred : IVSource.None, provider);
}
public DecryptingCipherParameters(Key key, String transformation, byte[] initializationVector, Provider provider) {
super(Cipher.DECRYPT_MODE, key, transformation, initializationVector, provider);
}
@@ -36,11 +44,6 @@ public class DecryptingCipherParameters extends CipherParameters {
throw new UnsupportedOperationException();
}
@Override
public boolean isGenerateInitializationVector() {
throw new UnsupportedOperationException();
}
@Override
public DecryptingCipherParameters setGenerateInitializationVector(boolean generateInitializationVector) {
throw new UnsupportedOperationException();

View File

@@ -27,6 +27,8 @@ public class DigestBuffer extends AbstractBuffer {
if (this.logger.isDebugEnabled())
this.logger.debug("digest algorithm: " + this.digest.getAlgorithm());
this.initialized = true;
this.leftoverBuffer = ByteBuffer.allocate(this.digest.getDigestLength());
this.leftoverBuffer.flip();
}

View File

@@ -15,8 +15,8 @@ public class EncryptingCipherParameters extends CipherParameters {
super(Cipher.ENCRYPT_MODE, key, transformation);
}
public EncryptingCipherParameters(Key key, String transformation, boolean generateInitializationVector) {
super(Cipher.ENCRYPT_MODE, key, transformation, generateInitializationVector);
public EncryptingCipherParameters(Key key, String transformation, IVSource ivSource) {
super(Cipher.ENCRYPT_MODE, key, transformation, ivSource);
}
public EncryptingCipherParameters(Key key, String transformation, byte[] initializationVector) {
@@ -31,8 +31,8 @@ public class EncryptingCipherParameters extends CipherParameters {
super(Cipher.ENCRYPT_MODE, key, transformation, provider);
}
public EncryptingCipherParameters(Key key, String transformation, boolean generateInitializationVector, Provider provider) {
super(Cipher.ENCRYPT_MODE, key, transformation, generateInitializationVector, provider);
public EncryptingCipherParameters(Key key, String transformation, IVSource ivSource, Provider provider) {
super(Cipher.ENCRYPT_MODE, key, transformation, ivSource, provider);
}
public EncryptingCipherParameters(Key key, String transformation, byte[] initializationVector, Provider provider) {

View File

@@ -27,13 +27,13 @@ public class IVDecryptingReadableByteChannel implements ReadableByteChannel, Dec
public IVDecryptingReadableByteChannel(ReadableByteChannel rbchannel, Key key, String transformation)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
this.rbchannel = rbchannel;
this.drbchannel = new DecryptingReadableByteChannel(rbchannel, new DecryptingCipherParameters(key, transformation));
this.drbchannel = new DecryptingReadableByteChannel(rbchannel, new DecryptingCipherParameters(key, transformation, true));
}
public IVDecryptingReadableByteChannel(ReadableByteChannel rbchannel, Key key, String transformation, Provider provider)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
this.rbchannel = rbchannel;
this.drbchannel = new DecryptingReadableByteChannel(rbchannel, new DecryptingCipherParameters(key, transformation, provider));
this.drbchannel = new DecryptingReadableByteChannel(rbchannel, new DecryptingCipherParameters(key, transformation, true, provider));
}
@Override

View File

@@ -12,6 +12,8 @@ import java.security.Provider;
import javax.crypto.NoSuchPaddingException;
import com.inteligr8.nio.CipherParameters.IVSource;
/**
* This class embeds a random initialization vector at the start of the
* encrypted content. Otherwise it acts identical to the
@@ -28,7 +30,7 @@ public class IVEncryptingWritableByteChannel implements WritableByteChannel, Flu
public IVEncryptingWritableByteChannel(WritableByteChannel wbchannel, Key key, String transformation)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
this.wbchannel = wbchannel;
this.ewbchannel = new EncryptingWritableByteChannel(wbchannel, new EncryptingCipherParameters(key, transformation, true));
this.ewbchannel = new EncryptingWritableByteChannel(wbchannel, new EncryptingCipherParameters(key, transformation, IVSource.Generated));
}
public IVEncryptingWritableByteChannel(WritableByteChannel wbchannel, Key key, String transformation, byte[] iv)
@@ -40,7 +42,7 @@ public class IVEncryptingWritableByteChannel implements WritableByteChannel, Flu
public IVEncryptingWritableByteChannel(WritableByteChannel wbchannel, Key key, String transformation, Provider provider)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
this.wbchannel = wbchannel;
this.ewbchannel = new EncryptingWritableByteChannel(wbchannel, new EncryptingCipherParameters(key, transformation, true, provider));
this.ewbchannel = new EncryptingWritableByteChannel(wbchannel, new EncryptingCipherParameters(key, transformation, IVSource.Generated, provider));
}
public IVEncryptingWritableByteChannel(WritableByteChannel wbchannel, Key key, String transformation, byte[] iv, Provider provider)

View File

@@ -2,6 +2,7 @@ package com.inteligr8.nio;
public enum Status {
Uninitialized,
Initialized,
Started,
Finished

View File

@@ -52,7 +52,7 @@ public abstract class AbstractHashingByteChannelUnitTest {
@Test
public void javaDigestBuffer() throws Exception {
this.test("sha-256", new File("src/main/java/com/inteligr8/nio/DigestBuffer.java"), "d01c874ffb0c6633a5d6ff4537da36c44d50af856970abddc1215866b0d08f44");
this.test("sha-256", new File("src/main/java/com/inteligr8/nio/DigestBuffer.java"), "0cdd4be589eada9c9ff37160ed46b4951361dab6b7eb0bfc1234436e37b6edc7");
}
public void test(String algorithm, String text, String hex) throws Exception {

View File

@@ -33,11 +33,11 @@ public class IVCryptoByteChannelUnitTest extends AbstractCryptoByteChannelUnitTe
int keySizeInBytes = this.getKeySizeInBytes();
ByteBufferChannel bbchannel = new ByteBufferChannel(1024);
IVEncryptingWritableByteChannel ebchannel = new IVEncryptingWritableByteChannel(bbchannel, this.getKey(), "AES/CBC/NoPadding");
IVEncryptingWritableByteChannel ebchannel = new IVEncryptingWritableByteChannel(bbchannel, this.getKey(), "AES/CBC/PKCS5Padding");
try {
int bytesWritten = ebchannel.write(this.getCharset().encode(text));
if (text.length() == 0) Assert.assertEquals(keySizeInBytes, bytesWritten);
else Assert.assertEquals(this.getKeySizeInBytes() + Math.max(1, text.length() / keySizeInBytes * keySizeInBytes), bytesWritten);
else Assert.assertEquals(text.length() / keySizeInBytes * keySizeInBytes + keySizeInBytes, bytesWritten);
} finally {
ebchannel.close();
}
@@ -45,10 +45,11 @@ public class IVCryptoByteChannelUnitTest extends AbstractCryptoByteChannelUnitTe
Assert.assertTrue(bbchannel.size() >= text.length());
ByteBuffer bbuffer = ByteBuffer.allocate(1024);
IVDecryptingReadableByteChannel dbchannel = new IVDecryptingReadableByteChannel(bbchannel, this.getKey(), "AES/CBC/NoPadding");
IVDecryptingReadableByteChannel dbchannel = new IVDecryptingReadableByteChannel(bbchannel, this.getKey(), "AES/CBC/PKCS5Padding");
try {
int bytesRead = dbchannel.read(bbuffer);
int bytesRead = dbchannel.read(bbuffer);
Assert.assertEquals(text.length() / keySizeInBytes * keySizeInBytes + 2 * keySizeInBytes, bytesRead);
Assert.assertEquals(-1, dbchannel.read(bbuffer));
} finally {
dbchannel.close();
}
@@ -63,11 +64,10 @@ public class IVCryptoByteChannelUnitTest extends AbstractCryptoByteChannelUnitTe
bbuffer.limit(Math.min(chunkSize, realLimit));
ByteBufferChannel bbchannel = new ByteBufferChannel(1024);
IVEncryptingWritableByteChannel ebchannel = new IVEncryptingWritableByteChannel(bbchannel, getKey(), "AES/CBC/NoPadding");
IVEncryptingWritableByteChannel ebchannel = new IVEncryptingWritableByteChannel(bbchannel, getKey(), "AES/CBC/PKCS5Padding");
try {
int bytesWritten = 1;
while (bytesWritten > 0) {
bytesWritten = ebchannel.write(bbuffer);
while (bbuffer.hasRemaining()) {
ebchannel.write(bbuffer);
bbuffer.limit(Math.min(bbuffer.limit() + chunkSize, realLimit));
}
} finally {
@@ -79,7 +79,7 @@ public class IVCryptoByteChannelUnitTest extends AbstractCryptoByteChannelUnitTe
bbuffer = ByteBuffer.allocate(1024);
realLimit = bbuffer.limit();
bbuffer.limit(Math.min(chunkSize, realLimit));
IVDecryptingReadableByteChannel dbchannel = new IVDecryptingReadableByteChannel(bbchannel, getKey(), "AES/CBC/NoPadding");
IVDecryptingReadableByteChannel dbchannel = new IVDecryptingReadableByteChannel(bbchannel, getKey(), "AES/CBC/PKCS5Padding");
try {
int bytesRead = 1;
while (bytesRead >= 0) {
@@ -98,10 +98,10 @@ public class IVCryptoByteChannelUnitTest extends AbstractCryptoByteChannelUnitTe
int keySizeInBytes = this.getKeySizeInBytes();
ByteBufferChannel bbchannel = new ByteBufferChannel(1024);
IVEncryptingWritableByteChannel ebchannel = new IVEncryptingWritableByteChannel(bbchannel, this.getKey(), "AES/CBC/NoPadding");
IVEncryptingWritableByteChannel ebchannel = new IVEncryptingWritableByteChannel(bbchannel, this.getKey(), "AES/CBC/PKCS5Padding");
try {
int bytesWritten = ebchannel.write(this.getCharset().encode(text));
Assert.assertEquals(this.getKeySizeInBytes() + Math.max(1, text.length() / keySizeInBytes * keySizeInBytes), bytesWritten);
Assert.assertEquals(text.length() / keySizeInBytes * keySizeInBytes + keySizeInBytes, bytesWritten);
} finally {
ebchannel.close();
}
@@ -109,7 +109,7 @@ public class IVCryptoByteChannelUnitTest extends AbstractCryptoByteChannelUnitTe
Assert.assertTrue(bbchannel.size() >= text.length());
ByteBuffer bbuffer = ByteBuffer.allocate(startsWith.length());
IVDecryptingReadableByteChannel dbchannel = new IVDecryptingReadableByteChannel(bbchannel, this.getKey(), "AES/CBC/NoPadding");
IVDecryptingReadableByteChannel dbchannel = new IVDecryptingReadableByteChannel(bbchannel, this.getKey(), "AES/CBC/PKCS5Padding");
try {
int bytesRead = dbchannel.read(bbuffer);
Assert.assertEquals(startsWith.length() / keySizeInBytes * keySizeInBytes + 2 * keySizeInBytes, bytesRead);

View File

@@ -2,16 +2,18 @@ package com.inteligr8.nio;
import java.security.Key;
import com.inteligr8.nio.CipherParameters.IVSource;
public class IVSymmetricBlockCipherUnitTest extends SymmetricBlockCipherUnitTest {
@Override
public String getDefaultTransformation() {
return "AES/CBC/NoPadding";
return "AES/CBC/PKCS5Padding";
}
@Override
public CipherBuffer createCipher(int cipherMode, Key key, String transformation) throws Exception {
return new CipherBuffer(new CipherParameters(cipherMode, key, transformation, true));
return new CipherBuffer(new CipherParameters(cipherMode, key, transformation, IVSource.Generated));
}
public CipherBuffer createCipher(int cipherMode, Key key, String transformation, CipherBuffer cipher) throws Exception {

View File

@@ -68,7 +68,7 @@ public class StreamingCryptoByteChannelUnitTest {
SocketChannel channel = SocketChannel.open();
Assert.assertTrue(channel.connect(new InetSocketAddress("localhost", port)));
IVEncryptingWritableByteChannel ebchannel = new IVEncryptingWritableByteChannel(channel, key, "AES/CBC/NoPadding");
IVEncryptingWritableByteChannel ebchannel = new IVEncryptingWritableByteChannel(channel, key, "AES/CBC/PKCS5Padding");
ByteBuffer bbuffer = ByteBuffer.allocate(bufferSize);
while (fchannel.read(bbuffer) >= 0) {
@@ -100,7 +100,7 @@ public class StreamingCryptoByteChannelUnitTest {
schannel.socket().bind(new InetSocketAddress(port));
SocketChannel channel = schannel.accept();
IVDecryptingReadableByteChannel dbchannel = new IVDecryptingReadableByteChannel(channel, key, "AES/CBC/NoPadding");
IVDecryptingReadableByteChannel dbchannel = new IVDecryptingReadableByteChannel(channel, key, "AES/CBC/PKCS5Padding");
ByteBuffer bbuffer = ByteBuffer.allocate(bufferSize);
ByteBuffer fbuffer = ByteBuffer.allocate(bufferSize);