added uninit status; added deferred iv; various related fixes
This commit is contained in:
@@ -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() {
|
||||
|
@@ -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()");
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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) {
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -2,6 +2,7 @@ package com.inteligr8.nio;
|
||||
|
||||
public enum Status {
|
||||
|
||||
Uninitialized,
|
||||
Initialized,
|
||||
Started,
|
||||
Finished
|
||||
|
@@ -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 {
|
||||
|
@@ -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);
|
||||
|
@@ -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 {
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user