mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Replaced encrypted IVs with pseudo-random tags.
This commit is contained in:
@@ -27,13 +27,11 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
private static final String DIGEST_ALGO = "SHA-256";
|
||||
private static final String KEY_PAIR_ALGO = "ECDSA";
|
||||
private static final int KEY_PAIR_BITS = 256;
|
||||
private static final String FRAME_CIPHER_ALGO = "AES/CTR/NoPadding";
|
||||
private static final String CIPHER_ALGO = "AES/CTR/NoPadding";
|
||||
private static final String SECRET_KEY_ALGO = "AES";
|
||||
private static final int SECRET_KEY_BYTES = 32; // 256 bits
|
||||
private static final String TAG_CIPHER_ALGO = "AES/ECB/NoPadding";
|
||||
private static final String MAC_ALGO = "HMacSHA256";
|
||||
private static final String SIGNATURE_ALGO = "ECDSA";
|
||||
private static final String KEY_DERIVATION_ALGO = "AES/CTR/NoPadding";
|
||||
private static final int KEY_DERIVATION_IV_BYTES = 16; // 128 bits
|
||||
|
||||
// Labels for key derivation, null-terminated
|
||||
@@ -104,7 +102,7 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
assert ivBytes[ivBytes.length - 1] == 0;
|
||||
IvParameterSpec iv = new IvParameterSpec(ivBytes);
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance(KEY_DERIVATION_ALGO, PROVIDER);
|
||||
Cipher cipher = Cipher.getInstance(CIPHER_ALGO, PROVIDER);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
|
||||
byte[] output = cipher.doFinal(KEY_DERIVATION_INPUT);
|
||||
assert output.length == SECRET_KEY_BYTES;
|
||||
@@ -137,7 +135,7 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
|
||||
public Cipher getFrameCipher() {
|
||||
try {
|
||||
return Cipher.getInstance(FRAME_CIPHER_ALGO, PROVIDER);
|
||||
return Cipher.getInstance(CIPHER_ALGO, PROVIDER);
|
||||
} catch(GeneralSecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -178,7 +176,7 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
|
||||
public Cipher getTagCipher() {
|
||||
try {
|
||||
return Cipher.getInstance(TAG_CIPHER_ALGO, PROVIDER);
|
||||
return Cipher.getInstance(CIPHER_ALGO, PROVIDER);
|
||||
} catch(GeneralSecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||
|
||||
import java.io.EOFException;
|
||||
@@ -13,10 +12,11 @@ import java.security.InvalidKeyException;
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import javax.crypto.ShortBufferException;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
|
||||
class ConnectionDecrypterImpl extends FilterInputStream
|
||||
implements ConnectionDecrypter {
|
||||
|
||||
@@ -28,14 +28,13 @@ implements ConnectionDecrypter {
|
||||
private long frame = 0L;
|
||||
private boolean betweenFrames = true;
|
||||
|
||||
ConnectionDecrypterImpl(InputStream in, byte[] iv, Cipher frameCipher,
|
||||
ConnectionDecrypterImpl(InputStream in, Cipher frameCipher,
|
||||
ErasableKey frameKey) {
|
||||
super(in);
|
||||
if(iv.length != TAG_LENGTH) throw new IllegalArgumentException();
|
||||
this.iv = iv;
|
||||
this.frameCipher = frameCipher;
|
||||
this.frameKey = frameKey;
|
||||
buf = new byte[TAG_LENGTH];
|
||||
iv = IvEncoder.encodeIv(0, frameCipher.getBlockSize());
|
||||
buf = new byte[frameCipher.getBlockSize()];
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
|
||||
@@ -25,27 +25,17 @@ implements ConnectionEncrypter {
|
||||
private long capacity, frame = 0L;
|
||||
private boolean tagWritten = false, betweenFrames = false;
|
||||
|
||||
ConnectionEncrypterImpl(OutputStream out, long capacity, byte[] iv,
|
||||
Cipher tagCipher, Cipher frameCipher, ErasableKey tagKey,
|
||||
ErasableKey frameKey) {
|
||||
ConnectionEncrypterImpl(OutputStream out, long capacity, Cipher tagCipher,
|
||||
Cipher frameCipher, ErasableKey tagKey, ErasableKey frameKey) {
|
||||
super(out);
|
||||
this.capacity = capacity;
|
||||
this.iv = iv;
|
||||
this.frameCipher = frameCipher;
|
||||
this.frameKey = frameKey;
|
||||
iv = IvEncoder.encodeIv(0, frameCipher.getBlockSize());
|
||||
// Encrypt the tag
|
||||
try {
|
||||
tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
|
||||
tag = tagCipher.doFinal(iv);
|
||||
} catch(BadPaddingException badCipher) {
|
||||
throw new IllegalArgumentException(badCipher);
|
||||
} catch(IllegalBlockSizeException badCipher) {
|
||||
throw new IllegalArgumentException(badCipher);
|
||||
} catch(InvalidKeyException badKey) {
|
||||
throw new IllegalArgumentException(badKey);
|
||||
}
|
||||
if(tag.length != TAG_LENGTH) throw new IllegalArgumentException();
|
||||
tag = TagEncoder.encodeTag(0, tagCipher, tagKey);
|
||||
tagKey.erase();
|
||||
if(tag.length != TAG_LENGTH) throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.security.InvalidKeyException;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.Mac;
|
||||
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
@@ -28,26 +25,12 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
|
||||
|
||||
public ConnectionReader createConnectionReader(InputStream in,
|
||||
ConnectionContext ctx, byte[] tag) {
|
||||
// Decrypt the tag
|
||||
// Validate the tag
|
||||
Cipher tagCipher = crypto.getTagCipher();
|
||||
ErasableKey tagKey = crypto.deriveTagKey(ctx.getSecret(), true);
|
||||
byte[] iv;
|
||||
try {
|
||||
tagCipher.init(Cipher.DECRYPT_MODE, tagKey);
|
||||
iv = tagCipher.doFinal(tag);
|
||||
} catch(BadPaddingException badCipher) {
|
||||
throw new IllegalArgumentException(badCipher);
|
||||
} catch(IllegalBlockSizeException badCipher) {
|
||||
throw new IllegalArgumentException(badCipher);
|
||||
} catch(InvalidKeyException badKey) {
|
||||
throw new IllegalArgumentException(badKey);
|
||||
}
|
||||
boolean valid = TagEncoder.validateTag(tag, 0, tagCipher, tagKey);
|
||||
tagKey.erase();
|
||||
// Validate the tag
|
||||
int index = ctx.getTransportIndex().getInt();
|
||||
long connection = ctx.getConnectionNumber();
|
||||
if(!IvEncoder.validateIv(iv, index, connection))
|
||||
throw new IllegalArgumentException();
|
||||
if(!valid) throw new IllegalArgumentException();
|
||||
return createConnectionReader(in, true, ctx);
|
||||
}
|
||||
|
||||
@@ -64,11 +47,8 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
|
||||
ErasableKey macKey = crypto.deriveMacKey(secret, initiator);
|
||||
ByteUtils.erase(secret);
|
||||
// Create the decrypter
|
||||
int index = ctx.getTransportIndex().getInt();
|
||||
long connection = ctx.getConnectionNumber();
|
||||
byte[] iv = IvEncoder.encodeIv(index, connection);
|
||||
Cipher frameCipher = crypto.getFrameCipher();
|
||||
ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in, iv,
|
||||
ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in,
|
||||
frameCipher, frameKey);
|
||||
// Create the reader
|
||||
Mac mac = crypto.getMac();
|
||||
|
||||
@@ -2,7 +2,6 @@ package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@@ -15,9 +14,7 @@ import java.util.concurrent.Executor;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
|
||||
import net.sf.briar.api.Bytes;
|
||||
import net.sf.briar.api.ContactId;
|
||||
@@ -103,22 +100,10 @@ DatabaseListener {
|
||||
|
||||
// Locking: this
|
||||
private Bytes calculateTag(Context ctx, byte[] secret) {
|
||||
byte[] iv = IvEncoder.encodeIv(ctx.transportIndex.getInt(),
|
||||
ctx.connection);
|
||||
ErasableKey tagKey = crypto.deriveTagKey(secret, true);
|
||||
try {
|
||||
tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
|
||||
byte[] tag = tagCipher.doFinal(iv);
|
||||
return new Bytes(tag);
|
||||
} catch(BadPaddingException badCipher) {
|
||||
throw new RuntimeException(badCipher);
|
||||
} catch(IllegalBlockSizeException badCipher) {
|
||||
throw new RuntimeException(badCipher);
|
||||
} catch(InvalidKeyException badKey) {
|
||||
throw new RuntimeException(badKey);
|
||||
} finally {
|
||||
tagKey.erase();
|
||||
}
|
||||
byte[] tag = TagEncoder.encodeTag(0, tagCipher, tagKey);
|
||||
tagKey.erase();
|
||||
return new Bytes(tag);
|
||||
}
|
||||
|
||||
public void acceptConnection(final TransportId t, final byte[] tag,
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.security.InvalidKeyException;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.Mac;
|
||||
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
@@ -36,23 +33,9 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
|
||||
// Decrypt the tag
|
||||
Cipher tagCipher = crypto.getTagCipher();
|
||||
ErasableKey tagKey = crypto.deriveTagKey(ctx.getSecret(), true);
|
||||
byte[] iv;
|
||||
try {
|
||||
tagCipher.init(Cipher.DECRYPT_MODE, tagKey);
|
||||
iv = tagCipher.doFinal(tag);
|
||||
} catch(BadPaddingException badCipher) {
|
||||
throw new RuntimeException(badCipher);
|
||||
} catch(IllegalBlockSizeException badCipher) {
|
||||
throw new RuntimeException(badCipher);
|
||||
} catch(InvalidKeyException badKey) {
|
||||
throw new RuntimeException(badKey);
|
||||
}
|
||||
boolean valid = TagEncoder.validateTag(tag, 0, tagCipher, tagKey);
|
||||
tagKey.erase();
|
||||
// Validate the tag
|
||||
int index = ctx.getTransportIndex().getInt();
|
||||
long connection = ctx.getConnectionNumber();
|
||||
if(!IvEncoder.validateIv(iv, index, connection))
|
||||
throw new IllegalArgumentException();
|
||||
if(!valid) throw new IllegalArgumentException();
|
||||
return createConnectionWriter(out, capacity, false, ctx);
|
||||
}
|
||||
|
||||
@@ -65,13 +48,10 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
|
||||
ErasableKey macKey = crypto.deriveMacKey(secret, initiator);
|
||||
ByteUtils.erase(secret);
|
||||
// Create the encrypter
|
||||
int index = ctx.getTransportIndex().getInt();
|
||||
long connection = ctx.getConnectionNumber();
|
||||
byte[] iv = IvEncoder.encodeIv(index, connection);
|
||||
Cipher tagCipher = crypto.getTagCipher();
|
||||
Cipher frameCipher = crypto.getFrameCipher();
|
||||
ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out,
|
||||
capacity, iv, tagCipher, frameCipher, tagKey, frameKey);
|
||||
capacity, tagCipher, frameCipher, tagKey, frameKey);
|
||||
// Create the writer
|
||||
Mac mac = crypto.getMac();
|
||||
return new ConnectionWriterImpl(encrypter, mac, macKey);
|
||||
|
||||
@@ -1,45 +1,19 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import net.sf.briar.util.ByteUtils;
|
||||
|
||||
class IvEncoder {
|
||||
|
||||
static byte[] encodeIv(int index, long connection) {
|
||||
byte[] iv = new byte[TAG_LENGTH];
|
||||
// Encode the transport index as an unsigned 16-bit integer
|
||||
ByteUtils.writeUint16(index, iv, 4);
|
||||
// Encode the connection number as an unsigned 32-bit integer
|
||||
ByteUtils.writeUint32(connection, iv, 6);
|
||||
static byte[] encodeIv(long frame, int blockSize) {
|
||||
if(frame > ByteUtils.MAX_32_BIT_UNSIGNED)
|
||||
throw new IllegalArgumentException();
|
||||
byte[] iv = new byte[blockSize];
|
||||
updateIv(iv, frame);
|
||||
return iv;
|
||||
}
|
||||
|
||||
static void updateIv(byte[] iv, long frame) {
|
||||
if(iv.length != TAG_LENGTH) throw new IllegalArgumentException();
|
||||
// Encode the frame number as an unsigned 32-bit integer
|
||||
ByteUtils.writeUint32(frame, iv, 10);
|
||||
}
|
||||
|
||||
static boolean validateIv(byte[] iv, int index, long connection) {
|
||||
if(iv.length != TAG_LENGTH) return false;
|
||||
// Check that the reserved bits are all zero
|
||||
for(int i = 0; i < 3; i++) if(iv[i] != 0) return false;
|
||||
for(int i = 10; i < iv.length; i++) if(iv[i] != 0) return false;
|
||||
// Check that the transport index matches
|
||||
if(index != getTransportIndex(iv)) return false;
|
||||
// Check that the connection number matches
|
||||
if(connection != getConnectionNumber(iv)) return false;
|
||||
// The IV is valid
|
||||
return true;
|
||||
}
|
||||
|
||||
static int getTransportIndex(byte[] iv) {
|
||||
if(iv.length != TAG_LENGTH) throw new IllegalArgumentException();
|
||||
return ByteUtils.readUint16(iv, 4);
|
||||
}
|
||||
|
||||
static long getConnectionNumber(byte[] iv) {
|
||||
if(iv.length != TAG_LENGTH) throw new IllegalArgumentException();
|
||||
return ByteUtils.readUint32(iv, 6);
|
||||
// Encode the frame number as a uint32, leaving 2 bytes for the counter
|
||||
ByteUtils.writeUint32(frame, iv, iv.length - 6);
|
||||
}
|
||||
}
|
||||
|
||||
54
components/net/sf/briar/transport/TagEncoder.java
Normal file
54
components/net/sf/briar/transport/TagEncoder.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.api.transport.TransportConstants;
|
||||
import net.sf.briar.util.ByteUtils;
|
||||
|
||||
class TagEncoder {
|
||||
|
||||
static byte[] encodeTag(long frame, Cipher tagCipher, ErasableKey tagKey) {
|
||||
if(frame > ByteUtils.MAX_32_BIT_UNSIGNED)
|
||||
throw new IllegalArgumentException();
|
||||
// The plaintext is blank
|
||||
byte[] plaintext = new byte[TransportConstants.TAG_LENGTH];
|
||||
// Encode the frame number as a uint32 at the end of the IV
|
||||
byte[] iv = new byte[tagCipher.getBlockSize()];
|
||||
if(iv.length != plaintext.length) throw new IllegalArgumentException();
|
||||
ByteUtils.writeUint32(frame, iv, iv.length - 4);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
try {
|
||||
tagCipher.init(Cipher.ENCRYPT_MODE, tagKey, ivSpec);
|
||||
return tagCipher.doFinal(plaintext);
|
||||
} catch(GeneralSecurityException e) {
|
||||
// Unsuitable cipher or key
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean validateTag(byte[] tag, long frame, Cipher tagCipher,
|
||||
ErasableKey tagKey) {
|
||||
if(tag.length != TransportConstants.TAG_LENGTH) return false;
|
||||
// Encode the frame number as a uint32 at the end of the IV
|
||||
byte[] iv = new byte[tagCipher.getBlockSize()];
|
||||
if(iv.length != tag.length) throw new IllegalArgumentException();
|
||||
ByteUtils.writeUint32(frame, iv, iv.length - 4);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
try {
|
||||
tagCipher.init(Cipher.DECRYPT_MODE, tagKey, ivSpec);
|
||||
byte[] plaintext = tagCipher.doFinal(tag);
|
||||
// The plaintext should be blank
|
||||
for(int i = 0; i < plaintext.length; i++) {
|
||||
if(plaintext[i] != 0) return false;
|
||||
}
|
||||
return true;
|
||||
} catch(GeneralSecurityException e) {
|
||||
// Unsuitable cipher or key
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,16 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import net.sf.briar.TestUtils;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.protocol.TransportIndex;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.crypto.CryptoModule;
|
||||
|
||||
import org.apache.commons.io.output.ByteArrayOutputStream;
|
||||
@@ -25,18 +23,14 @@ public class ConnectionDecrypterImplTest extends TestCase {
|
||||
|
||||
private static final int MAC_LENGTH = 32;
|
||||
|
||||
private final Cipher tagCipher, frameCipher;
|
||||
private final ErasableKey tagKey, frameKey;
|
||||
private final TransportIndex transportIndex = new TransportIndex(13);
|
||||
private final long connection = 12345L;
|
||||
private final Cipher frameCipher;
|
||||
private final ErasableKey frameKey;
|
||||
|
||||
public ConnectionDecrypterImplTest() {
|
||||
super();
|
||||
Injector i = Guice.createInjector(new CryptoModule());
|
||||
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
||||
tagCipher = crypto.getTagCipher();
|
||||
frameCipher = crypto.getFrameCipher();
|
||||
tagKey = crypto.generateTestKey();
|
||||
frameKey = crypto.generateTestKey();
|
||||
}
|
||||
|
||||
@@ -51,12 +45,8 @@ public class ConnectionDecrypterImplTest extends TestCase {
|
||||
}
|
||||
|
||||
private void testDecryption(boolean initiator) throws Exception {
|
||||
// Calculate the plaintext and ciphertext for the IV
|
||||
byte[] iv = IvEncoder.encodeIv(transportIndex.getInt(), connection);
|
||||
tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
|
||||
byte[] tag = tagCipher.doFinal(iv);
|
||||
assertEquals(TAG_LENGTH, tag.length);
|
||||
// Calculate the expected plaintext for the first frame
|
||||
byte[] iv = new byte[frameCipher.getBlockSize()];
|
||||
byte[] ciphertext = new byte[123];
|
||||
byte[] ciphertextMac = new byte[MAC_LENGTH];
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
@@ -84,9 +74,8 @@ public class ConnectionDecrypterImplTest extends TestCase {
|
||||
out.write(ciphertextMac);
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||
// Use a ConnectionDecrypter to decrypt the ciphertext
|
||||
ConnectionDecrypter d = new ConnectionDecrypterImpl(in,
|
||||
IvEncoder.encodeIv(transportIndex.getInt(), connection),
|
||||
frameCipher, frameKey);
|
||||
ConnectionDecrypter d = new ConnectionDecrypterImpl(in, frameCipher,
|
||||
frameKey);
|
||||
// First frame
|
||||
byte[] decrypted = new byte[ciphertext.length];
|
||||
TestUtils.readFully(d.getInputStream(), decrypted);
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.protocol.TransportIndex;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.crypto.CryptoModule;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -25,8 +23,6 @@ public class ConnectionEncrypterImplTest extends TestCase {
|
||||
|
||||
private final Cipher tagCipher, frameCipher;
|
||||
private final ErasableKey tagKey, frameKey;
|
||||
private final TransportIndex transportIndex = new TransportIndex(13);
|
||||
private final long connection = 12345L;
|
||||
|
||||
public ConnectionEncrypterImplTest() {
|
||||
super();
|
||||
@@ -49,12 +45,10 @@ public class ConnectionEncrypterImplTest extends TestCase {
|
||||
}
|
||||
|
||||
private void testEncryption(boolean initiator) throws Exception {
|
||||
// Calculate the expected ciphertext for the IV
|
||||
byte[] iv = IvEncoder.encodeIv(transportIndex.getInt(), connection);
|
||||
tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
|
||||
byte[] tag = tagCipher.doFinal(iv);
|
||||
assertEquals(TAG_LENGTH, tag.length);
|
||||
// Calculate the expected tag
|
||||
byte[] tag = TagEncoder.encodeTag(0, tagCipher, tagKey);
|
||||
// Calculate the expected ciphertext for the first frame
|
||||
byte[] iv = new byte[frameCipher.getBlockSize()];
|
||||
byte[] plaintext = new byte[123];
|
||||
byte[] plaintextMac = new byte[MAC_LENGTH];
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
@@ -82,9 +76,8 @@ public class ConnectionEncrypterImplTest extends TestCase {
|
||||
byte[] expected = out.toByteArray();
|
||||
// Use a ConnectionEncrypter to encrypt the plaintext
|
||||
out.reset();
|
||||
iv = IvEncoder.encodeIv(transportIndex.getInt(), connection);
|
||||
ConnectionEncrypter e = new ConnectionEncrypterImpl(out, Long.MAX_VALUE,
|
||||
iv, tagCipher, frameCipher, tagKey, frameKey);
|
||||
tagCipher, frameCipher, tagKey, frameKey);
|
||||
e.getOutputStream().write(plaintext);
|
||||
e.writeMac(plaintextMac);
|
||||
e.getOutputStream().write(plaintext1);
|
||||
|
||||
@@ -617,8 +617,6 @@ public class ConnectionRecogniserImplTest extends TestCase {
|
||||
// Calculate the expected tag for connection number 3
|
||||
ErasableKey tagKey = crypto.deriveTagKey(secret, true);
|
||||
Cipher tagCipher = crypto.getTagCipher();
|
||||
tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
|
||||
byte[] iv = IvEncoder.encodeIv(remoteIndex.getInt(), 3);
|
||||
return tagCipher.doFinal(iv);
|
||||
return TagEncoder.encodeTag(0, tagCipher, tagKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,10 @@ import java.util.Random;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.Mac;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.protocol.TransportIndex;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.api.transport.ConnectionReader;
|
||||
import net.sf.briar.api.transport.ConnectionWriter;
|
||||
import net.sf.briar.crypto.CryptoModule;
|
||||
@@ -33,8 +32,6 @@ public class FrameReadWriteTest extends TestCase {
|
||||
private final byte[] outSecret;
|
||||
private final ErasableKey tagKey, frameKey, macKey;
|
||||
private final Mac mac;
|
||||
private final TransportIndex transportIndex = new TransportIndex(13);
|
||||
private final long connection = 12345L;
|
||||
|
||||
public FrameReadWriteTest() {
|
||||
super();
|
||||
@@ -63,11 +60,8 @@ public class FrameReadWriteTest extends TestCase {
|
||||
}
|
||||
|
||||
private void testWriteAndRead(boolean initiator) throws Exception {
|
||||
// Create and encrypt the IV
|
||||
byte[] iv = IvEncoder.encodeIv(transportIndex.getInt(), connection);
|
||||
tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
|
||||
byte[] tag = tagCipher.doFinal(iv);
|
||||
assertEquals(TAG_LENGTH, tag.length);
|
||||
// Encode the tag
|
||||
byte[] tag = TagEncoder.encodeTag(0, tagCipher, tagKey);
|
||||
// Generate two random frames
|
||||
byte[] frame = new byte[12345];
|
||||
random.nextBytes(frame);
|
||||
@@ -80,7 +74,7 @@ public class FrameReadWriteTest extends TestCase {
|
||||
// Write the frames
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out,
|
||||
Long.MAX_VALUE, iv, tagCipher, frameCipher, tagCopy, frameCopy);
|
||||
Long.MAX_VALUE, tagCipher, frameCipher, tagCopy, frameCopy);
|
||||
ConnectionWriter writer = new ConnectionWriterImpl(encrypter, mac,
|
||||
macCopy);
|
||||
OutputStream out1 = writer.getOutputStream();
|
||||
@@ -88,18 +82,14 @@ public class FrameReadWriteTest extends TestCase {
|
||||
out1.flush();
|
||||
out1.write(frame1);
|
||||
out1.flush();
|
||||
// Read the IV back
|
||||
// Read the tag back
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||
byte[] recoveredTag = new byte[TAG_LENGTH];
|
||||
assertEquals(TAG_LENGTH, in.read(recoveredTag));
|
||||
assertArrayEquals(tag, recoveredTag);
|
||||
// Decrypt the IV
|
||||
tagCipher.init(Cipher.DECRYPT_MODE, tagKey);
|
||||
byte[] recoveredIv = tagCipher.doFinal(recoveredTag);
|
||||
iv = IvEncoder.encodeIv(transportIndex.getInt(), connection);
|
||||
assertArrayEquals(iv, recoveredIv);
|
||||
assertTrue(TagEncoder.validateTag(tag, 0, tagCipher, tagKey));
|
||||
// Read the frames back
|
||||
ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in, iv,
|
||||
ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in,
|
||||
frameCipher, frameKey);
|
||||
ConnectionReader reader = new ConnectionReaderImpl(decrypter, mac,
|
||||
macKey);
|
||||
|
||||
Reference in New Issue
Block a user