Implement stream header for BTPv2. #111

This commit is contained in:
akwizgran
2015-12-14 13:29:28 +00:00
parent 766179ac97
commit f2efe7f2ea
9 changed files with 591 additions and 233 deletions

View File

@@ -1,37 +1,226 @@
package org.briarproject.crypto;
import org.briarproject.BriarTestCase;
import org.briarproject.TestUtils;
import org.briarproject.api.crypto.SecretKey;
import org.briarproject.util.ByteUtils;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Random;
import static junit.framework.Assert.assertEquals;
import static org.briarproject.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
import static org.briarproject.api.transport.TransportConstants.MAC_LENGTH;
import static org.briarproject.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.fail;
public class StreamDecrypterImplTest extends BriarTestCase {
private final AuthenticatedCipher cipher;
private final SecretKey streamHeaderKey, frameKey;
private final byte[] streamHeaderIv;
private final Random random;
public StreamDecrypterImplTest() {
cipher = new TestAuthenticatedCipher(); // Null cipher
streamHeaderKey = TestUtils.createSecretKey();
frameKey = TestUtils.createSecretKey();
streamHeaderIv = new byte[STREAM_HEADER_IV_LENGTH];
random = new Random();
random.nextBytes(streamHeaderIv);
}
@Test
public void testReadValidFrames() throws Exception {
// FIXME
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
int payloadLength = 123, paddingLength = 234;
FrameEncoder.encodeHeader(frameHeader, false, payloadLength,
paddingLength);
byte[] payload = new byte[payloadLength];
random.nextBytes(payload);
byte[] frameHeader1 = new byte[FRAME_HEADER_LENGTH];
int payloadLength1 = 345, paddingLength1 = 456;
FrameEncoder.encodeHeader(frameHeader1, true, payloadLength1,
paddingLength1);
byte[] payload1 = new byte[payloadLength1];
random.nextBytes(payload1);
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(streamHeaderIv);
out.write(frameKey.getBytes());
out.write(new byte[MAC_LENGTH]);
out.write(frameHeader);
out.write(payload);
out.write(new byte[paddingLength]);
out.write(new byte[MAC_LENGTH]);
out.write(frameHeader1);
out.write(payload1);
out.write(new byte[paddingLength1]);
out.write(new byte[MAC_LENGTH]);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
streamHeaderKey);
// Read the first frame
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
assertEquals(payloadLength, s.readFrame(buffer));
assertArrayStartsWith(payload, buffer, payloadLength);
// Read the second frame
assertEquals(payloadLength1, s.readFrame(buffer));
assertArrayStartsWith(payload1, buffer, payloadLength1);
// End of stream
assertEquals(-1, s.readFrame(buffer));
}
@Test
public void testTruncatedFrameThrowsException() throws Exception {
// FIXME
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
int payloadLength = 123, paddingLength = 234;
FrameEncoder.encodeHeader(frameHeader, false, payloadLength,
paddingLength);
byte[] payload = new byte[payloadLength];
random.nextBytes(payload);
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(streamHeaderIv);
out.write(frameKey.getBytes());
out.write(new byte[MAC_LENGTH]);
out.write(frameHeader);
out.write(payload);
out.write(new byte[paddingLength]);
out.write(new byte[MAC_LENGTH - 1]); // Chop off the last byte
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
streamHeaderKey);
// Try to read the truncated frame
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
try {
s.readFrame(buffer);
fail();
} catch (IOException expected) {
// Expected
}
}
@Test
public void testModifiedFrameThrowsException() throws Exception {
// FIXME
}
public void testInvalidPayloadAndPaddingLengthThrowsException()
throws Exception {
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
// The payload length plus padding length is invalid
int payloadLength = MAX_PAYLOAD_LENGTH - 1, paddingLength = 2;
ByteUtils.writeUint16(payloadLength, frameHeader, 0);
ByteUtils.writeUint16(paddingLength, frameHeader, 2);
byte[] payload = new byte[payloadLength];
random.nextBytes(payload);
@Test
public void testInvalidPayloadLengthThrowsException() throws Exception {
// FIXME
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(streamHeaderIv);
out.write(frameKey.getBytes());
out.write(new byte[MAC_LENGTH]);
out.write(frameHeader);
out.write(payload);
out.write(new byte[paddingLength]);
out.write(new byte[MAC_LENGTH]);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
streamHeaderKey);
// Try to read the invalid frame
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
try {
s.readFrame(buffer);
fail();
} catch (IOException expected) {
// Expected
}
}
@Test
public void testNonZeroPaddingThrowsException() throws Exception {
// FIXME
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
int payloadLength = 123, paddingLength = 234;
FrameEncoder.encodeHeader(frameHeader, false, payloadLength,
paddingLength);
byte[] payload = new byte[payloadLength];
random.nextBytes(payload);
// Set one of the padding bytes non-zero
byte[] padding = new byte[paddingLength];
padding[paddingLength - 1] = 1;
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(streamHeaderIv);
out.write(frameKey.getBytes());
out.write(new byte[MAC_LENGTH]);
out.write(frameHeader);
out.write(payload);
out.write(padding);
out.write(new byte[MAC_LENGTH]);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
streamHeaderKey);
// Try to read the invalid frame
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
try {
s.readFrame(buffer);
fail();
} catch (IOException expected) {
// Expected
}
}
@Test
public void testCannotReadBeyondFinalFrame() throws Exception {
// FIXME
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
int payloadLength = 123, paddingLength = 234;
FrameEncoder.encodeHeader(frameHeader, true, payloadLength,
paddingLength);
byte[] payload = new byte[payloadLength];
random.nextBytes(payload);
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(streamHeaderIv);
out.write(frameKey.getBytes());
out.write(new byte[MAC_LENGTH]);
out.write(frameHeader);
out.write(payload);
out.write(new byte[paddingLength]);
out.write(new byte[MAC_LENGTH]);
// Add some data beyond the final frame
out.write(new byte[1024]);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
streamHeaderKey);
// Read the first frame
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
assertEquals(payloadLength, s.readFrame(buffer));
assertArrayStartsWith(payload, buffer, payloadLength);
// End of stream
assertEquals(-1, s.readFrame(buffer));
// Yup, definitely end of stream
assertEquals(-1, s.readFrame(buffer));
}
private static void assertArrayStartsWith(byte[] expected, byte[] actual,
int len) {
byte[] prefix = new byte[len];
System.arraycopy(actual, 0, prefix, 0, len);
assertArrayEquals(expected, prefix);
}
}

View File

@@ -1,261 +1,345 @@
package org.briarproject.crypto;
import org.briarproject.BriarTestCase;
import org.briarproject.TestUtils;
import org.briarproject.api.crypto.SecretKey;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.util.Random;
import static org.briarproject.api.transport.TransportConstants.HEADER_LENGTH;
import static org.briarproject.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
import static org.briarproject.api.transport.TransportConstants.MAC_LENGTH;
import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
public class StreamEncrypterImplTest extends BriarTestCase {
private final AuthenticatedCipher frameCipher;
private final SecretKey frameKey;
private final byte[] tag;
private final AuthenticatedCipher cipher;
private final SecretKey streamHeaderKey, frameKey;
private final byte[] tag, streamHeaderIv;
private final Random random;
public StreamEncrypterImplTest() {
frameCipher = new TestAuthenticatedCipher();
frameKey = new SecretKey(new byte[32]);
cipher = new TestAuthenticatedCipher(); // Null cipher
streamHeaderKey = TestUtils.createSecretKey();
frameKey = TestUtils.createSecretKey();
tag = new byte[TAG_LENGTH];
new Random().nextBytes(tag);
streamHeaderIv = new byte[STREAM_HEADER_IV_LENGTH];
random = new Random();
random.nextBytes(tag);
random.nextBytes(streamHeaderIv);
}
@Test
public void testWriteUnpaddedNonFinalFrameWithTag() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
frameKey, tag);
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, tag,
streamHeaderIv, streamHeaderKey, frameKey);
int payloadLength = 123;
byte[] payload = new byte[payloadLength];
new Random().nextBytes(payload);
random.nextBytes(payload);
s.writeFrame(payload, payloadLength, 0, false);
byte[] header = new byte[HEADER_LENGTH];
FrameEncoder.encodeHeader(header, false, payloadLength, 0);
int frameLength = HEADER_LENGTH + payloadLength + MAC_LENGTH;
byte[] expected = new byte[TAG_LENGTH + frameLength];
System.arraycopy(tag, 0, expected, 0, TAG_LENGTH);
System.arraycopy(header, 0, expected, TAG_LENGTH, HEADER_LENGTH);
System.arraycopy(payload, 0, expected, TAG_LENGTH + HEADER_LENGTH,
payloadLength);
assertArrayEquals(expected, out.toByteArray());
// Expect the tag, stream header, frame header, payload and MAC
ByteArrayOutputStream expected = new ByteArrayOutputStream();
expected.write(tag);
expected.write(streamHeaderIv);
expected.write(frameKey.getBytes());
expected.write(new byte[MAC_LENGTH]);
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
FrameEncoder.encodeHeader(expectedFrameHeader, false, payloadLength, 0);
expected.write(expectedFrameHeader);
expected.write(payload);
expected.write(new byte[MAC_LENGTH]);
assertArrayEquals(expected.toByteArray(), out.toByteArray());
}
@Test
public void testWriteUnpaddedFinalFrameWithTag() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
frameKey, tag);
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, tag,
streamHeaderIv, streamHeaderKey, frameKey);
int payloadLength = 123;
int frameLength = HEADER_LENGTH + payloadLength + MAC_LENGTH;
byte[] payload = new byte[payloadLength];
new Random().nextBytes(payload);
random.nextBytes(payload);
s.writeFrame(payload, payloadLength, 0, true);
byte[] header = new byte[HEADER_LENGTH];
FrameEncoder.encodeHeader(header, true, payloadLength, 0);
byte[] expected = new byte[TAG_LENGTH + frameLength];
System.arraycopy(tag, 0, expected, 0, TAG_LENGTH);
System.arraycopy(header, 0, expected, TAG_LENGTH, HEADER_LENGTH);
System.arraycopy(payload, 0, expected, TAG_LENGTH + HEADER_LENGTH,
payloadLength);
assertArrayEquals(expected, out.toByteArray());
// Expect the tag, stream header, frame header, payload and MAC
ByteArrayOutputStream expected = new ByteArrayOutputStream();
expected.write(tag);
expected.write(streamHeaderIv);
expected.write(frameKey.getBytes());
expected.write(new byte[MAC_LENGTH]);
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
FrameEncoder.encodeHeader(expectedFrameHeader, true, payloadLength, 0);
expected.write(expectedFrameHeader);
expected.write(payload);
expected.write(new byte[MAC_LENGTH]);
assertArrayEquals(expected.toByteArray(), out.toByteArray());
}
@Test
public void testWriteUnpaddedNonFinalFrameWithoutTag() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
frameKey, null);
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, null,
streamHeaderIv, streamHeaderKey, frameKey);
int payloadLength = 123;
int frameLength = HEADER_LENGTH + payloadLength + MAC_LENGTH;
byte[] payload = new byte[payloadLength];
new Random().nextBytes(payload);
random.nextBytes(payload);
s.writeFrame(payload, payloadLength, 0, false);
byte[] header = new byte[HEADER_LENGTH];
FrameEncoder.encodeHeader(header, false, payloadLength, 0);
byte[] expected = new byte[frameLength];
System.arraycopy(header, 0, expected, 0, HEADER_LENGTH);
System.arraycopy(payload, 0, expected, HEADER_LENGTH, payloadLength);
assertArrayEquals(expected, out.toByteArray());
// Expect the stream header, frame header, payload and MAC
ByteArrayOutputStream expected = new ByteArrayOutputStream();
expected.write(streamHeaderIv);
expected.write(frameKey.getBytes());
expected.write(new byte[MAC_LENGTH]);
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
FrameEncoder.encodeHeader(expectedFrameHeader, false, payloadLength, 0);
expected.write(expectedFrameHeader);
expected.write(payload);
expected.write(new byte[MAC_LENGTH]);
assertArrayEquals(expected.toByteArray(), out.toByteArray());
}
@Test
public void testWriteUnpaddedFinalFrameWithoutTag() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
frameKey, null);
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, null,
streamHeaderIv, streamHeaderKey, frameKey);
int payloadLength = 123;
int frameLength = HEADER_LENGTH + payloadLength + MAC_LENGTH;
byte[] payload = new byte[payloadLength];
new Random().nextBytes(payload);
random.nextBytes(payload);
s.writeFrame(payload, payloadLength, 0, true);
byte[] header = new byte[HEADER_LENGTH];
FrameEncoder.encodeHeader(header, true, payloadLength, 0);
byte[] expected = new byte[frameLength];
System.arraycopy(header, 0, expected, 0, HEADER_LENGTH);
System.arraycopy(payload, 0, expected, HEADER_LENGTH, payloadLength);
assertArrayEquals(expected, out.toByteArray());
// Expect the stream header, frame header, payload and MAC
ByteArrayOutputStream expected = new ByteArrayOutputStream();
expected.write(streamHeaderIv);
expected.write(frameKey.getBytes());
expected.write(new byte[MAC_LENGTH]);
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
FrameEncoder.encodeHeader(expectedFrameHeader, true, payloadLength, 0);
expected.write(expectedFrameHeader);
expected.write(payload);
expected.write(new byte[MAC_LENGTH]);
assertArrayEquals(expected.toByteArray(), out.toByteArray());
}
@Test
public void testWritePaddedNonFinalFrameWithTag() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
frameKey, tag);
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, tag,
streamHeaderIv, streamHeaderKey, frameKey);
int payloadLength = 123, paddingLength = 234;
int frameLength = HEADER_LENGTH + payloadLength + paddingLength
+ MAC_LENGTH;
byte[] payload = new byte[payloadLength];
new Random().nextBytes(payload);
random.nextBytes(payload);
s.writeFrame(payload, payloadLength, paddingLength, false);
byte[] header = new byte[HEADER_LENGTH];
FrameEncoder.encodeHeader(header, false, payloadLength, paddingLength);
byte[] expected = new byte[TAG_LENGTH + frameLength];
System.arraycopy(tag, 0, expected, 0, TAG_LENGTH);
System.arraycopy(header, 0, expected, TAG_LENGTH, HEADER_LENGTH);
System.arraycopy(payload, 0, expected, TAG_LENGTH + HEADER_LENGTH,
payloadLength);
assertArrayEquals(expected, out.toByteArray());
// Expect the tag, stream header, frame header, payload, padding and MAC
ByteArrayOutputStream expected = new ByteArrayOutputStream();
expected.write(tag);
expected.write(streamHeaderIv);
expected.write(frameKey.getBytes());
expected.write(new byte[MAC_LENGTH]);
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
FrameEncoder.encodeHeader(expectedFrameHeader, false, payloadLength,
paddingLength);
expected.write(expectedFrameHeader);
expected.write(payload);
expected.write(new byte[paddingLength]);
expected.write(new byte[MAC_LENGTH]);
assertArrayEquals(expected.toByteArray(), out.toByteArray());
}
@Test
public void testWritePaddedFinalFrameWithTag() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
frameKey, tag);
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, tag,
streamHeaderIv, streamHeaderKey, frameKey);
int payloadLength = 123, paddingLength = 234;
int frameLength = HEADER_LENGTH + payloadLength + paddingLength
+ MAC_LENGTH;
byte[] payload = new byte[payloadLength];
new Random().nextBytes(payload);
random.nextBytes(payload);
s.writeFrame(payload, payloadLength, paddingLength, true);
byte[] header = new byte[HEADER_LENGTH];
FrameEncoder.encodeHeader(header, true, payloadLength, paddingLength);
byte[] expected = new byte[TAG_LENGTH + frameLength];
System.arraycopy(tag, 0, expected, 0, TAG_LENGTH);
System.arraycopy(header, 0, expected, TAG_LENGTH, HEADER_LENGTH);
System.arraycopy(payload, 0, expected, TAG_LENGTH + HEADER_LENGTH,
payloadLength);
assertArrayEquals(expected, out.toByteArray());
// Expect the tag, stream header, frame header, payload, padding and MAC
ByteArrayOutputStream expected = new ByteArrayOutputStream();
expected.write(tag);
expected.write(streamHeaderIv);
expected.write(frameKey.getBytes());
expected.write(new byte[MAC_LENGTH]);
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
FrameEncoder.encodeHeader(expectedFrameHeader, true, payloadLength,
paddingLength);
expected.write(expectedFrameHeader);
expected.write(payload);
expected.write(new byte[paddingLength]);
expected.write(new byte[MAC_LENGTH]);
assertArrayEquals(expected.toByteArray(), out.toByteArray());
}
@Test
public void testWritePaddedNonFinalFrameWithoutTag() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
frameKey, null);
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, null,
streamHeaderIv, streamHeaderKey, frameKey);
int payloadLength = 123, paddingLength = 234;
int frameLength = HEADER_LENGTH + payloadLength + paddingLength
+ MAC_LENGTH;
byte[] payload = new byte[payloadLength];
new Random().nextBytes(payload);
random.nextBytes(payload);
s.writeFrame(payload, payloadLength, paddingLength, false);
byte[] header = new byte[HEADER_LENGTH];
FrameEncoder.encodeHeader(header, false, payloadLength, paddingLength);
byte[] expected = new byte[frameLength];
System.arraycopy(header, 0, expected, 0, HEADER_LENGTH);
System.arraycopy(payload, 0, expected, HEADER_LENGTH, payloadLength);
assertArrayEquals(expected, out.toByteArray());
// Expect the stream header, frame header, payload, padding and MAC
ByteArrayOutputStream expected = new ByteArrayOutputStream();
expected.write(streamHeaderIv);
expected.write(frameKey.getBytes());
expected.write(new byte[MAC_LENGTH]);
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
FrameEncoder.encodeHeader(expectedFrameHeader, false, payloadLength,
paddingLength);
expected.write(expectedFrameHeader);
expected.write(payload);
expected.write(new byte[paddingLength]);
expected.write(new byte[MAC_LENGTH]);
assertArrayEquals(expected.toByteArray(), out.toByteArray());
}
@Test
public void testWritePaddedFinalFrameWithoutTag() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
frameKey, null);
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, null,
streamHeaderIv, streamHeaderKey, frameKey);
int payloadLength = 123, paddingLength = 234;
int frameLength = HEADER_LENGTH + payloadLength + paddingLength
+ MAC_LENGTH;
byte[] payload = new byte[payloadLength];
new Random().nextBytes(payload);
random.nextBytes(payload);
s.writeFrame(payload, payloadLength, paddingLength, true);
byte[] header = new byte[HEADER_LENGTH];
FrameEncoder.encodeHeader(header, true, payloadLength, paddingLength);
byte[] expected = new byte[frameLength];
System.arraycopy(header, 0, expected, 0, HEADER_LENGTH);
System.arraycopy(payload, 0, expected, HEADER_LENGTH, payloadLength);
assertArrayEquals(expected, out.toByteArray());
// Expect the stream header, frame header, payload, padding and MAC
ByteArrayOutputStream expected = new ByteArrayOutputStream();
expected.write(streamHeaderIv);
expected.write(frameKey.getBytes());
expected.write(new byte[MAC_LENGTH]);
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
FrameEncoder.encodeHeader(expectedFrameHeader, true, payloadLength,
paddingLength);
expected.write(expectedFrameHeader);
expected.write(payload);
expected.write(new byte[paddingLength]);
expected.write(new byte[MAC_LENGTH]);
assertArrayEquals(expected.toByteArray(), out.toByteArray());
}
@Test
public void testWriteTwoFrames() throws Exception {
public void testWriteTwoFramesWithTag() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
frameKey, null);
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, tag,
streamHeaderIv, streamHeaderKey, frameKey);
int payloadLength = 123, paddingLength = 234;
int frameLength = HEADER_LENGTH + payloadLength + paddingLength
+ MAC_LENGTH;
byte[] payload = new byte[payloadLength];
new Random().nextBytes(payload);
random.nextBytes(payload);
int payloadLength1 = 345, paddingLength1 = 456;
int frameLength1 = HEADER_LENGTH + payloadLength1 + paddingLength1
+ MAC_LENGTH;
byte[] payload1 = new byte[payloadLength1];
new Random().nextBytes(payload1);
random.nextBytes(payload1);
s.writeFrame(payload, payloadLength, paddingLength, false);
s.writeFrame(payload1, payloadLength1, paddingLength1, true);
byte[] header = new byte[HEADER_LENGTH];
FrameEncoder.encodeHeader(header, false, payloadLength, paddingLength);
byte[] header1 = new byte[HEADER_LENGTH];
FrameEncoder.encodeHeader(header1, true, payloadLength1,
// Expect the tag, stream header, first frame header, payload, padding,
// MAC, second frame header, payload, padding, MAC
ByteArrayOutputStream expected = new ByteArrayOutputStream();
expected.write(tag);
expected.write(streamHeaderIv);
expected.write(frameKey.getBytes());
expected.write(new byte[MAC_LENGTH]);
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
FrameEncoder.encodeHeader(expectedFrameHeader, false, payloadLength,
paddingLength);
expected.write(expectedFrameHeader);
expected.write(payload);
expected.write(new byte[paddingLength]);
expected.write(new byte[MAC_LENGTH]);
byte[] expectedFrameHeader1 = new byte[FRAME_HEADER_LENGTH];
FrameEncoder.encodeHeader(expectedFrameHeader1, true, payloadLength1,
paddingLength1);
byte[] expected = new byte[frameLength + frameLength1];
System.arraycopy(header, 0, expected, 0, HEADER_LENGTH);
System.arraycopy(payload, 0, expected, HEADER_LENGTH, payloadLength);
System.arraycopy(header1, 0, expected, frameLength, HEADER_LENGTH);
System.arraycopy(payload1, 0, expected, frameLength + HEADER_LENGTH,
payloadLength1);
assertArrayEquals(expected, out.toByteArray());
expected.write(expectedFrameHeader1);
expected.write(payload1);
expected.write(new byte[paddingLength1]);
expected.write(new byte[MAC_LENGTH]);
assertArrayEquals(expected.toByteArray(), out.toByteArray());
}
@Test
public void testFlushWritesTagIfNotAlreadyWritten() throws Exception {
public void testFlushWritesTagAndStreamHeaderIfNotAlreadyWritten()
throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
frameKey, tag);
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, tag,
streamHeaderIv, streamHeaderKey, frameKey);
// Flush the stream once
s.flush();
assertArrayEquals(tag, out.toByteArray());
// Expect the tag and stream header
ByteArrayOutputStream expected = new ByteArrayOutputStream();
expected.write(tag);
expected.write(streamHeaderIv);
expected.write(frameKey.getBytes());
expected.write(new byte[MAC_LENGTH]);
assertArrayEquals(expected.toByteArray(), out.toByteArray());
}
@Test
public void testFlushDoesNotWriteTagIfAlreadyWritten() throws Exception {
public void testFlushDoesNotWriteTagOrStreamHeaderIfAlreadyWritten()
throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
frameKey, tag);
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, tag,
streamHeaderIv, streamHeaderKey, frameKey);
// Flush the stream twice
s.flush();
s.flush();
assertArrayEquals(tag, out.toByteArray());
// Expect the tag and stream header
ByteArrayOutputStream expected = new ByteArrayOutputStream();
expected.write(tag);
expected.write(streamHeaderIv);
expected.write(frameKey.getBytes());
expected.write(new byte[MAC_LENGTH]);
assertArrayEquals(expected.toByteArray(), out.toByteArray());
}
@Test
public void testFlushDoesNotWriteTagIfNull() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
frameKey, null);
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, null,
streamHeaderIv, streamHeaderKey, frameKey);
// Flush the stream once
s.flush();
assertEquals(0, out.size());
// Expect the stream header
ByteArrayOutputStream expected = new ByteArrayOutputStream();
expected.write(streamHeaderIv);
expected.write(frameKey.getBytes());
expected.write(new byte[MAC_LENGTH]);
assertArrayEquals(expected.toByteArray(), out.toByteArray());
}
}

View File

@@ -8,7 +8,7 @@ import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import static org.briarproject.api.transport.TransportConstants.HEADER_LENGTH;
import static org.briarproject.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
import static org.briarproject.api.transport.TransportConstants.MAC_LENGTH;
import static org.briarproject.api.transport.TransportConstants.MAX_FRAME_LENGTH;
@@ -24,8 +24,8 @@ class TestStreamDecrypter implements StreamDecrypter {
public int readFrame(byte[] payload) throws IOException {
int offset = 0;
while (offset < HEADER_LENGTH) {
int read = in.read(frame, offset, HEADER_LENGTH - offset);
while (offset < FRAME_HEADER_LENGTH) {
int read = in.read(frame, offset, FRAME_HEADER_LENGTH - offset);
if (read == -1) throw new EOFException();
offset += read;
}
@@ -37,9 +37,9 @@ class TestStreamDecrypter implements StreamDecrypter {
offset += read;
}
if (!finalFrame && offset < frame.length) throw new EOFException();
if (offset < HEADER_LENGTH + payloadLength + MAC_LENGTH)
if (offset < FRAME_HEADER_LENGTH + payloadLength + MAC_LENGTH)
throw new FormatException();
System.arraycopy(frame, HEADER_LENGTH, payload, 0, payloadLength);
System.arraycopy(frame, FRAME_HEADER_LENGTH, payload, 0, payloadLength);
return payloadLength;
}
}

View File

@@ -6,7 +6,7 @@ import org.briarproject.util.ByteUtils;
import java.io.IOException;
import java.io.OutputStream;
import static org.briarproject.api.transport.TransportConstants.HEADER_LENGTH;
import static org.briarproject.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
import static org.briarproject.api.transport.TransportConstants.MAC_LENGTH;
import static org.briarproject.api.transport.TransportConstants.MAX_FRAME_LENGTH;
@@ -31,11 +31,11 @@ class TestStreamEncrypter implements StreamEncrypter {
}
ByteUtils.writeUint16(payloadLength, frame, 0);
if (finalFrame) frame[0] |= 0x80;
System.arraycopy(payload, 0, frame, HEADER_LENGTH, payloadLength);
for (int i = HEADER_LENGTH + payloadLength; i < frame.length; i++)
System.arraycopy(payload, 0, frame, FRAME_HEADER_LENGTH, payloadLength);
for (int i = FRAME_HEADER_LENGTH + payloadLength; i < frame.length; i++)
frame[i] = 0;
if (finalFrame)
out.write(frame, 0, HEADER_LENGTH + payloadLength + MAC_LENGTH);
out.write(frame, 0, FRAME_HEADER_LENGTH + payloadLength + MAC_LENGTH);
else out.write(frame, 0, frame.length);
}