mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 19:29:06 +01:00
Use AES/GCM instead of AES/CTR and HMAC.
This makes us Suite B compliant and saves 32 bytes per frame. The AES/GCM implementation refuses to decrypt the frame header before checking the MAC, so we have to use AES/CTR to peek at the header. The header is still covered by the MAC, and we still check it after peeking!
This commit is contained in:
44
test/net/sf/briar/crypto/FramePeekingTest.java
Normal file
44
test/net/sf/briar/crypto/FramePeekingTest.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package net.sf.briar.crypto;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
|
||||
import net.sf.briar.BriarTestCase;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.api.crypto.IvEncoder;
|
||||
import net.sf.briar.util.ByteUtils;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class FramePeekingTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testFramePeeking() throws Exception {
|
||||
CryptoComponent crypto = new CryptoComponentImpl();
|
||||
ErasableKey key = crypto.generateTestKey();
|
||||
|
||||
Cipher frameCipher = crypto.getFrameCipher();
|
||||
IvEncoder frameIvEncoder = crypto.getFrameIvEncoder();
|
||||
byte[] iv = frameIvEncoder.encodeIv(ByteUtils.MAX_32_BIT_UNSIGNED);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
frameCipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
|
||||
|
||||
Cipher framePeekingCipher = crypto.getFramePeekingCipher();
|
||||
IvEncoder framePeekingIvEncoder = crypto.getFramePeekingIvEncoder();
|
||||
iv = framePeekingIvEncoder.encodeIv(ByteUtils.MAX_32_BIT_UNSIGNED);
|
||||
ivSpec = new IvParameterSpec(iv);
|
||||
framePeekingCipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
|
||||
|
||||
// The ciphers should produce the same ciphertext, apart from the MAC
|
||||
byte[] plaintext = new byte[123];
|
||||
byte[] ciphertext = frameCipher.doFinal(plaintext);
|
||||
byte[] peekingCiphertext = framePeekingCipher.doFinal(plaintext);
|
||||
assertEquals(ciphertext.length, peekingCiphertext.length + MAC_LENGTH);
|
||||
for(int i = 0; i < peekingCiphertext.length; i++) {
|
||||
assertEquals(ciphertext[i], peekingCiphertext[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,17 +25,15 @@ public class KeyDerivationTest extends BriarTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSixKeysAreDistinct() {
|
||||
public void testKeysAreDistinct() {
|
||||
List<ErasableKey> keys = new ArrayList<ErasableKey>();
|
||||
keys.add(crypto.deriveFrameKey(secret, true));
|
||||
keys.add(crypto.deriveFrameKey(secret, false));
|
||||
keys.add(crypto.deriveTagKey(secret, true));
|
||||
keys.add(crypto.deriveTagKey(secret, false));
|
||||
keys.add(crypto.deriveMacKey(secret, true));
|
||||
keys.add(crypto.deriveMacKey(secret, false));
|
||||
for(int i = 0; i < 6; i++) {
|
||||
for(int i = 0; i < 4; i++) {
|
||||
byte[] keyI = keys.get(i).getEncoded();
|
||||
for(int j = 0; j < 6; j++) {
|
||||
for(int j = 0; j < 4; j++) {
|
||||
byte[] keyJ = keys.get(j).getEncoded();
|
||||
assertEquals(i == j, Arrays.equals(keyI, keyJ));
|
||||
}
|
||||
|
||||
@@ -23,14 +23,8 @@ public class ConnectionReaderImplTest extends TransportTest {
|
||||
|
||||
@Test
|
||||
public void testLengthZero() throws Exception {
|
||||
int payloadLength = 0;
|
||||
byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength
|
||||
+ MAC_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0, true);
|
||||
// Calculate the MAC
|
||||
mac.init(macKey);
|
||||
mac.update(frame, 0, FRAME_HEADER_LENGTH + payloadLength);
|
||||
mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength);
|
||||
byte[] frame = new byte[FRAME_HEADER_LENGTH + MAC_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame, 0, 0, 0, true);
|
||||
// Read the frame
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(frame);
|
||||
ConnectionReader r = createConnectionReader(in);
|
||||
@@ -40,14 +34,8 @@ public class ConnectionReaderImplTest extends TransportTest {
|
||||
|
||||
@Test
|
||||
public void testLengthOne() throws Exception {
|
||||
int payloadLength = 1;
|
||||
byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength
|
||||
+ MAC_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0, true);
|
||||
// Calculate the MAC
|
||||
mac.init(macKey);
|
||||
mac.update(frame, 0, FRAME_HEADER_LENGTH + payloadLength);
|
||||
mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength);
|
||||
byte[] frame = new byte[FRAME_HEADER_LENGTH + 1 + MAC_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame, 0, 1, 0, true);
|
||||
// Read the frame
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(frame);
|
||||
ConnectionReader r = createConnectionReader(in);
|
||||
@@ -61,14 +49,9 @@ public class ConnectionReaderImplTest extends TransportTest {
|
||||
// First frame: max payload length
|
||||
byte[] frame = new byte[MAX_FRAME_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame, 0, MAX_PAYLOAD_LENGTH, 0, false);
|
||||
mac.init(macKey);
|
||||
mac.update(frame, 0, FRAME_HEADER_LENGTH + MAX_PAYLOAD_LENGTH);
|
||||
mac.doFinal(frame, FRAME_HEADER_LENGTH + MAX_PAYLOAD_LENGTH);
|
||||
// Second frame: max payload length plus one
|
||||
byte[] frame1 = new byte[MAX_FRAME_LENGTH + 1];
|
||||
HeaderEncoder.encodeHeader(frame1, 1, MAX_PAYLOAD_LENGTH + 1, 0, false);
|
||||
mac.update(frame1, 0, FRAME_HEADER_LENGTH + MAX_PAYLOAD_LENGTH + 1);
|
||||
mac.doFinal(frame1, FRAME_HEADER_LENGTH + MAX_PAYLOAD_LENGTH + 1);
|
||||
// Concatenate the frames
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(frame);
|
||||
@@ -93,15 +76,10 @@ public class ConnectionReaderImplTest extends TransportTest {
|
||||
byte[] frame = new byte[MAX_FRAME_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame, 0, MAX_PAYLOAD_LENGTH - paddingLength,
|
||||
paddingLength, false);
|
||||
mac.init(macKey);
|
||||
mac.update(frame, 0, FRAME_HEADER_LENGTH + MAX_PAYLOAD_LENGTH);
|
||||
mac.doFinal(frame, FRAME_HEADER_LENGTH + MAX_PAYLOAD_LENGTH);
|
||||
// Second frame: max payload length plus one, including padding
|
||||
byte[] frame1 = new byte[MAX_FRAME_LENGTH + 1];
|
||||
HeaderEncoder.encodeHeader(frame1, 1,
|
||||
MAX_PAYLOAD_LENGTH + 1 - paddingLength, paddingLength, false);
|
||||
mac.update(frame1, 0, FRAME_HEADER_LENGTH + MAX_PAYLOAD_LENGTH + 1);
|
||||
mac.doFinal(frame1, FRAME_HEADER_LENGTH + MAX_PAYLOAD_LENGTH + 1);
|
||||
// Concatenate the frames
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(frame);
|
||||
@@ -128,10 +106,6 @@ public class ConnectionReaderImplTest extends TransportTest {
|
||||
false);
|
||||
// Set a byte of the padding to a non-zero value
|
||||
frame[FRAME_HEADER_LENGTH + payloadLength] = 1;
|
||||
mac.init(macKey);
|
||||
mac.update(frame, 0, FRAME_HEADER_LENGTH + payloadLength
|
||||
+ paddingLength);
|
||||
mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength + paddingLength);
|
||||
// Read the frame
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(frame);
|
||||
ConnectionReader r = createConnectionReader(in);
|
||||
@@ -149,16 +123,11 @@ public class ConnectionReaderImplTest extends TransportTest {
|
||||
byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength
|
||||
+ MAC_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0, false);
|
||||
mac.init(macKey);
|
||||
mac.update(frame, 0, FRAME_HEADER_LENGTH + payloadLength);
|
||||
mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength);
|
||||
// Second frame: 1234-byte payload
|
||||
int payloadLength1 = 1234;
|
||||
byte[] frame1 = new byte[FRAME_HEADER_LENGTH + payloadLength1
|
||||
+ MAC_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame1, 1, payloadLength1, 0, true);
|
||||
mac.update(frame1, 0, FRAME_HEADER_LENGTH + payloadLength1);
|
||||
mac.doFinal(frame1, FRAME_HEADER_LENGTH + payloadLength1);
|
||||
// Concatenate the frames
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(frame);
|
||||
@@ -182,16 +151,11 @@ public class ConnectionReaderImplTest extends TransportTest {
|
||||
byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength
|
||||
+ MAC_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0, false);
|
||||
mac.init(macKey);
|
||||
mac.update(frame, 0, FRAME_HEADER_LENGTH + payloadLength);
|
||||
mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength);
|
||||
// Second frame: 1234-byte payload
|
||||
int payloadLength1 = 1234;
|
||||
byte[] frame1 = new byte[FRAME_HEADER_LENGTH + payloadLength1
|
||||
+ MAC_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame1, 1, payloadLength1, 0, false);
|
||||
mac.update(frame1, 0, FRAME_HEADER_LENGTH + payloadLength1);
|
||||
mac.doFinal(frame1, FRAME_HEADER_LENGTH + payloadLength1);
|
||||
// Concatenate the frames
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(frame);
|
||||
@@ -211,52 +175,8 @@ public class ConnectionReaderImplTest extends TransportTest {
|
||||
} catch(FormatException expected) {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorruptPayload() throws Exception {
|
||||
int payloadLength = 8;
|
||||
byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength
|
||||
+ MAC_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0, false);
|
||||
// Calculate the MAC
|
||||
mac.init(macKey);
|
||||
mac.update(frame, 0, FRAME_HEADER_LENGTH + payloadLength);
|
||||
mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength);
|
||||
// Modify the payload
|
||||
frame[12] ^= 1;
|
||||
// Try to read the frame - not a single byte should be read
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(frame);
|
||||
ConnectionReader r = createConnectionReader(in);
|
||||
try {
|
||||
r.getInputStream().read();
|
||||
fail();
|
||||
} catch(FormatException expected) {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorruptMac() throws Exception {
|
||||
int payloadLength = 8;
|
||||
byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength
|
||||
+ MAC_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0, false);
|
||||
// Calculate the MAC
|
||||
mac.init(macKey);
|
||||
mac.update(frame, 0, FRAME_HEADER_LENGTH + payloadLength);
|
||||
mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength);
|
||||
// Modify the MAC
|
||||
frame[17] ^= 1;
|
||||
// Try to read the frame - not a single byte should be read
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(frame);
|
||||
ConnectionReader r = createConnectionReader(in);
|
||||
try {
|
||||
r.getInputStream().read();
|
||||
fail();
|
||||
} catch(FormatException expected) {}
|
||||
}
|
||||
|
||||
private ConnectionReader createConnectionReader(InputStream in) {
|
||||
FrameReader encryption = new NullIncomingEncryptionLayer(in);
|
||||
FrameReader authentication = new IncomingAuthenticationLayerImpl(
|
||||
encryption, mac, macKey);
|
||||
return new ConnectionReaderImpl(authentication);
|
||||
return new ConnectionReaderImpl(encryption);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,14 +30,9 @@ public class ConnectionWriterImplTest extends TransportTest {
|
||||
|
||||
@Test
|
||||
public void testSingleByteFrame() throws Exception {
|
||||
int payloadLength = 1;
|
||||
byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength
|
||||
+ MAC_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0, false);
|
||||
// Calculate the MAC
|
||||
mac.init(macKey);
|
||||
mac.update(frame, 0, FRAME_HEADER_LENGTH + payloadLength);
|
||||
mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength);
|
||||
// Create a single-byte frame
|
||||
byte[] frame = new byte[FRAME_HEADER_LENGTH + 1 + MAC_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame, 0, 1, 0, false);
|
||||
// Check that the ConnectionWriter gets the same results
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ConnectionWriter w = createConnectionWriter(out);
|
||||
@@ -75,20 +70,11 @@ public class ConnectionWriterImplTest extends TransportTest {
|
||||
@Test
|
||||
public void testMultipleFrames() throws Exception {
|
||||
// First frame: 123-byte payload
|
||||
int payloadLength = 123;
|
||||
byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength
|
||||
+ MAC_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0, false);
|
||||
mac.init(macKey);
|
||||
mac.update(frame, 0, FRAME_HEADER_LENGTH + payloadLength);
|
||||
mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength);
|
||||
byte[] frame = new byte[FRAME_HEADER_LENGTH + 123 + MAC_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame, 0, 123, 0, false);
|
||||
// Second frame: 1234-byte payload
|
||||
int payloadLength1 = 1234;
|
||||
byte[] frame1 = new byte[FRAME_HEADER_LENGTH + payloadLength1
|
||||
+ MAC_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame1, 1, payloadLength1, 0, false);
|
||||
mac.update(frame1, 0, FRAME_HEADER_LENGTH + 1234);
|
||||
mac.doFinal(frame1, FRAME_HEADER_LENGTH + 1234);
|
||||
byte[] frame1 = new byte[FRAME_HEADER_LENGTH + 1234 + MAC_LENGTH];
|
||||
HeaderEncoder.encodeHeader(frame1, 1, 1234, 0, false);
|
||||
// Concatenate the frames
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(frame);
|
||||
@@ -107,8 +93,6 @@ public class ConnectionWriterImplTest extends TransportTest {
|
||||
|
||||
private ConnectionWriter createConnectionWriter(OutputStream out) {
|
||||
FrameWriter encryption = new NullOutgoingEncryptionLayer(out);
|
||||
FrameWriter authentication =
|
||||
new OutgoingAuthenticationLayerImpl(encryption, mac, macKey);
|
||||
return new ConnectionWriterImpl(authentication);
|
||||
return new ConnectionWriterImpl(encryption);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@ import java.io.OutputStream;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.Mac;
|
||||
|
||||
import net.sf.briar.BriarTestCase;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.api.crypto.IvEncoder;
|
||||
import net.sf.briar.api.transport.ConnectionReader;
|
||||
import net.sf.briar.api.transport.ConnectionWriter;
|
||||
import net.sf.briar.crypto.CryptoModule;
|
||||
@@ -27,11 +27,11 @@ import com.google.inject.Injector;
|
||||
public class FrameReadWriteTest extends BriarTestCase {
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
private final Cipher tagCipher, frameCipher;
|
||||
private final Mac mac;
|
||||
private final Cipher tagCipher, frameCipher, framePeekingCipher;
|
||||
private final IvEncoder frameIvEncoder, framePeekingIvEncoder;
|
||||
private final Random random;
|
||||
private final byte[] outSecret;
|
||||
private final ErasableKey tagKey, frameKey, macKey;
|
||||
private final ErasableKey tagKey, frameKey;
|
||||
|
||||
public FrameReadWriteTest() {
|
||||
super();
|
||||
@@ -39,14 +39,15 @@ public class FrameReadWriteTest extends BriarTestCase {
|
||||
crypto = i.getInstance(CryptoComponent.class);
|
||||
tagCipher = crypto.getTagCipher();
|
||||
frameCipher = crypto.getFrameCipher();
|
||||
mac = crypto.getMac();
|
||||
framePeekingCipher = crypto.getFramePeekingCipher();
|
||||
frameIvEncoder = crypto.getFrameIvEncoder();
|
||||
framePeekingIvEncoder = crypto.getFramePeekingIvEncoder();
|
||||
random = new Random();
|
||||
// Since we're sending frames to ourselves, we only need outgoing keys
|
||||
outSecret = new byte[32];
|
||||
random.nextBytes(outSecret);
|
||||
tagKey = crypto.deriveTagKey(outSecret, true);
|
||||
frameKey = crypto.deriveFrameKey(outSecret, true);
|
||||
macKey = crypto.deriveMacKey(outSecret, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,14 +72,12 @@ public class FrameReadWriteTest extends BriarTestCase {
|
||||
// Copy the keys - the copies will be erased
|
||||
ErasableKey tagCopy = tagKey.copy();
|
||||
ErasableKey frameCopy = frameKey.copy();
|
||||
ErasableKey macCopy = macKey.copy();
|
||||
// Write the frames
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
FrameWriter encryptionOut = new OutgoingEncryptionLayerImpl(out,
|
||||
Long.MAX_VALUE, tagCipher, frameCipher, tagCopy, frameCopy);
|
||||
FrameWriter authenticationOut = new OutgoingAuthenticationLayerImpl(
|
||||
encryptionOut, mac, macCopy);
|
||||
ConnectionWriter writer = new ConnectionWriterImpl(authenticationOut);
|
||||
Long.MAX_VALUE, tagCipher, frameCipher, frameIvEncoder, tagCopy,
|
||||
frameCopy);
|
||||
ConnectionWriter writer = new ConnectionWriterImpl(encryptionOut);
|
||||
OutputStream out1 = writer.getOutputStream();
|
||||
out1.write(frame);
|
||||
out1.flush();
|
||||
@@ -92,10 +91,9 @@ public class FrameReadWriteTest extends BriarTestCase {
|
||||
assertTrue(TagEncoder.decodeTag(recoveredTag, tagCipher, tagKey));
|
||||
// Read the frames back
|
||||
FrameReader encryptionIn = new IncomingEncryptionLayerImpl(in,
|
||||
tagCipher, frameCipher, tagKey, frameKey, false);
|
||||
FrameReader authenticationIn = new IncomingAuthenticationLayerImpl(
|
||||
encryptionIn, mac, macKey);
|
||||
ConnectionReader reader = new ConnectionReaderImpl(authenticationIn);
|
||||
tagCipher, frameCipher, framePeekingCipher, frameIvEncoder,
|
||||
framePeekingIvEncoder, tagKey, frameKey, false);
|
||||
ConnectionReader reader = new ConnectionReaderImpl(encryptionIn);
|
||||
InputStream in1 = reader.getInputStream();
|
||||
byte[] recovered = new byte[frame.length];
|
||||
int offset = 0;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -12,6 +11,7 @@ import javax.crypto.spec.IvParameterSpec;
|
||||
import net.sf.briar.BriarTestCase;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.api.crypto.IvEncoder;
|
||||
import net.sf.briar.crypto.CryptoModule;
|
||||
|
||||
import org.apache.commons.io.output.ByteArrayOutputStream;
|
||||
@@ -22,7 +22,8 @@ import com.google.inject.Injector;
|
||||
|
||||
public class IncomingEncryptionLayerImplTest extends BriarTestCase {
|
||||
|
||||
private final Cipher tagCipher, frameCipher;
|
||||
private final Cipher tagCipher, frameCipher, framePeekingCipher;
|
||||
private final IvEncoder frameIvEncoder, framePeekingIvEncoder;
|
||||
private final ErasableKey tagKey, frameKey;
|
||||
|
||||
public IncomingEncryptionLayerImplTest() {
|
||||
@@ -31,6 +32,9 @@ public class IncomingEncryptionLayerImplTest extends BriarTestCase {
|
||||
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
||||
tagCipher = crypto.getTagCipher();
|
||||
frameCipher = crypto.getFrameCipher();
|
||||
framePeekingCipher = crypto.getFramePeekingCipher();
|
||||
frameIvEncoder = crypto.getFrameIvEncoder();
|
||||
framePeekingIvEncoder = crypto.getFramePeekingIvEncoder();
|
||||
tagKey = crypto.generateTestKey();
|
||||
frameKey = crypto.generateTestKey();
|
||||
}
|
||||
@@ -41,16 +45,16 @@ public class IncomingEncryptionLayerImplTest extends BriarTestCase {
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
TagEncoder.encodeTag(tag, tagCipher, tagKey);
|
||||
// Calculate the ciphertext for the first frame
|
||||
byte[] plaintext = new byte[FRAME_HEADER_LENGTH + 123 + MAC_LENGTH];
|
||||
byte[] plaintext = new byte[FRAME_HEADER_LENGTH + 123];
|
||||
HeaderEncoder.encodeHeader(plaintext, 0L, 123, 0, false);
|
||||
byte[] iv = IvEncoder.encodeIv(0L, frameCipher.getBlockSize());
|
||||
byte[] iv = frameIvEncoder.encodeIv(0L);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec);
|
||||
byte[] ciphertext = frameCipher.doFinal(plaintext, 0, plaintext.length);
|
||||
byte[] ciphertext = frameCipher.doFinal(plaintext);
|
||||
// Calculate the ciphertext for the second frame
|
||||
byte[] plaintext1 = new byte[FRAME_HEADER_LENGTH + 1234 + MAC_LENGTH];
|
||||
byte[] plaintext1 = new byte[FRAME_HEADER_LENGTH + 1234];
|
||||
HeaderEncoder.encodeHeader(plaintext1, 1L, 1234, 0, false);
|
||||
IvEncoder.updateIv(iv, 1L);
|
||||
frameIvEncoder.updateIv(iv, 1L);
|
||||
ivSpec = new IvParameterSpec(iv);
|
||||
frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec);
|
||||
byte[] ciphertext1 = frameCipher.doFinal(plaintext1, 0,
|
||||
@@ -63,7 +67,8 @@ public class IncomingEncryptionLayerImplTest extends BriarTestCase {
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||
// Use the encryption layer to decrypt the ciphertext
|
||||
FrameReader decrypter = new IncomingEncryptionLayerImpl(in, tagCipher,
|
||||
frameCipher, tagKey, frameKey, true);
|
||||
frameCipher, framePeekingCipher, frameIvEncoder,
|
||||
framePeekingIvEncoder, tagKey, frameKey, true);
|
||||
// First frame
|
||||
Frame f = new Frame();
|
||||
assertTrue(decrypter.readFrame(f));
|
||||
@@ -86,16 +91,16 @@ public class IncomingEncryptionLayerImplTest extends BriarTestCase {
|
||||
@Test
|
||||
public void testDecryptionWithoutTag() throws Exception {
|
||||
// Calculate the ciphertext for the first frame
|
||||
byte[] plaintext = new byte[FRAME_HEADER_LENGTH + 123 + MAC_LENGTH];
|
||||
byte[] plaintext = new byte[FRAME_HEADER_LENGTH + 123];
|
||||
HeaderEncoder.encodeHeader(plaintext, 0L, 123, 0, false);
|
||||
byte[] iv = IvEncoder.encodeIv(0L, frameCipher.getBlockSize());
|
||||
byte[] iv = frameIvEncoder.encodeIv(0L);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec);
|
||||
byte[] ciphertext = frameCipher.doFinal(plaintext, 0, plaintext.length);
|
||||
byte[] ciphertext = frameCipher.doFinal(plaintext);
|
||||
// Calculate the ciphertext for the second frame
|
||||
byte[] plaintext1 = new byte[FRAME_HEADER_LENGTH + 1234 + MAC_LENGTH];
|
||||
byte[] plaintext1 = new byte[FRAME_HEADER_LENGTH + 1234];
|
||||
HeaderEncoder.encodeHeader(plaintext1, 1L, 1234, 0, false);
|
||||
IvEncoder.updateIv(iv, 1L);
|
||||
frameIvEncoder.updateIv(iv, 1L);
|
||||
ivSpec = new IvParameterSpec(iv);
|
||||
frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec);
|
||||
byte[] ciphertext1 = frameCipher.doFinal(plaintext1, 0,
|
||||
@@ -107,7 +112,8 @@ public class IncomingEncryptionLayerImplTest extends BriarTestCase {
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||
// Use the encryption layer to decrypt the ciphertext
|
||||
FrameReader decrypter = new IncomingEncryptionLayerImpl(in, tagCipher,
|
||||
frameCipher, tagKey, frameKey, false);
|
||||
frameCipher, framePeekingCipher, frameIvEncoder,
|
||||
framePeekingIvEncoder, tagKey, frameKey, false);
|
||||
// First frame
|
||||
Frame f = new Frame();
|
||||
assertTrue(decrypter.readFrame(f));
|
||||
|
||||
@@ -42,7 +42,7 @@ class NullIncomingEncryptionLayer implements FrameReader {
|
||||
if(read == -1) throw new EOFException();
|
||||
offset += read;
|
||||
}
|
||||
f.setLength(length);
|
||||
f.setLength(length - MAC_LENGTH);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
@@ -21,7 +23,7 @@ class NullOutgoingEncryptionLayer implements FrameWriter {
|
||||
}
|
||||
|
||||
public void writeFrame(Frame f) throws IOException {
|
||||
out.write(f.getBuffer(), 0, f.getLength());
|
||||
out.write(f.getBuffer(), 0, f.getLength() + MAC_LENGTH);
|
||||
capacity -= f.getLength();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import javax.crypto.spec.IvParameterSpec;
|
||||
import net.sf.briar.BriarTestCase;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.api.crypto.IvEncoder;
|
||||
import net.sf.briar.crypto.CryptoModule;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -20,9 +21,8 @@ import com.google.inject.Injector;
|
||||
|
||||
public class OutgoingEncryptionLayerImplTest extends BriarTestCase {
|
||||
|
||||
private static final int MAC_LENGTH = 32;
|
||||
|
||||
private final Cipher tagCipher, frameCipher;
|
||||
private final IvEncoder frameIvEncoder;
|
||||
private final ErasableKey tagKey, frameKey;
|
||||
|
||||
public OutgoingEncryptionLayerImplTest() {
|
||||
@@ -31,6 +31,7 @@ public class OutgoingEncryptionLayerImplTest extends BriarTestCase {
|
||||
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
||||
tagCipher = crypto.getTagCipher();
|
||||
frameCipher = crypto.getFrameCipher();
|
||||
frameIvEncoder = crypto.getFrameIvEncoder();
|
||||
tagKey = crypto.generateTestKey();
|
||||
frameKey = crypto.generateTestKey();
|
||||
}
|
||||
@@ -41,14 +42,14 @@ public class OutgoingEncryptionLayerImplTest extends BriarTestCase {
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
TagEncoder.encodeTag(tag, tagCipher, tagKey);
|
||||
// Calculate the expected ciphertext for the first frame
|
||||
byte[] iv = new byte[frameCipher.getBlockSize()];
|
||||
byte[] plaintext = new byte[123 + MAC_LENGTH];
|
||||
byte[] iv = frameIvEncoder.encodeIv(0L);
|
||||
byte[] plaintext = new byte[123];
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec);
|
||||
byte[] ciphertext = frameCipher.doFinal(plaintext);
|
||||
// Calculate the expected ciphertext for the second frame
|
||||
byte[] plaintext1 = new byte[1234 + MAC_LENGTH];
|
||||
IvEncoder.updateIv(iv, 1L);
|
||||
byte[] plaintext1 = new byte[1234];
|
||||
frameIvEncoder.updateIv(iv, 1L);
|
||||
ivSpec = new IvParameterSpec(iv);
|
||||
frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec);
|
||||
byte[] ciphertext1 = frameCipher.doFinal(plaintext1);
|
||||
@@ -61,7 +62,8 @@ public class OutgoingEncryptionLayerImplTest extends BriarTestCase {
|
||||
// Use the encryption layer to encrypt the plaintext
|
||||
out.reset();
|
||||
FrameWriter encrypter = new OutgoingEncryptionLayerImpl(out,
|
||||
Long.MAX_VALUE, tagCipher, frameCipher, tagKey, frameKey);
|
||||
Long.MAX_VALUE, tagCipher, frameCipher, frameIvEncoder, tagKey,
|
||||
frameKey);
|
||||
Frame f = new Frame();
|
||||
System.arraycopy(plaintext, 0, f.getBuffer(), 0, plaintext.length);
|
||||
f.setLength(plaintext.length);
|
||||
|
||||
@@ -4,7 +4,7 @@ import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
import net.sf.briar.BriarTestCase;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
@@ -19,14 +19,14 @@ public abstract class TransportTest extends BriarTestCase {
|
||||
static final int MAX_PAYLOAD_LENGTH =
|
||||
MAX_FRAME_LENGTH - FRAME_HEADER_LENGTH - MAC_LENGTH;
|
||||
|
||||
protected final Mac mac;
|
||||
protected final ErasableKey macKey;
|
||||
protected final Cipher frameCipher;
|
||||
protected final ErasableKey frameKey;
|
||||
|
||||
public TransportTest() throws Exception {
|
||||
super();
|
||||
Injector i = Guice.createInjector(new CryptoModule());
|
||||
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
||||
mac = crypto.getMac();
|
||||
macKey = crypto.generateTestKey();
|
||||
frameCipher = crypto.getFrameCipher();
|
||||
frameKey = crypto.generateTestKey();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user