mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 14:19:53 +01:00
Merge branch '329-btp-header' into 'master'
Include stream number in stream header nonce
See the corresponding change in the BTP spec for an explanation:
388e1d23c0
Closes #329
See merge request !320
This commit is contained in:
@@ -122,7 +122,7 @@ public class SyncIntegrationTest extends BriarTestCase {
|
|||||||
|
|
||||||
// Create the readers
|
// Create the readers
|
||||||
StreamContext ctx = new StreamContext(contactId, transportId, tagKey,
|
StreamContext ctx = new StreamContext(contactId, transportId, tagKey,
|
||||||
headerKey, 0);
|
headerKey, streamNumber);
|
||||||
InputStream streamReader = streamReaderFactory.createStreamReader(in,
|
InputStream streamReader = streamReaderFactory.createStreamReader(in,
|
||||||
ctx);
|
ctx);
|
||||||
PacketReader packetReader = packetReaderFactory.createPacketReader(
|
PacketReader packetReader = packetReaderFactory.createPacketReader(
|
||||||
|
|||||||
@@ -8,11 +8,14 @@ public interface TransportConstants {
|
|||||||
/** The length of the pseudo-random tag in bytes. */
|
/** The length of the pseudo-random tag in bytes. */
|
||||||
int TAG_LENGTH = 16;
|
int TAG_LENGTH = 16;
|
||||||
|
|
||||||
/** The length of the message authentication code (MAC) in bytes. */
|
/** The length of the stream header nonce in bytes. */
|
||||||
int MAC_LENGTH = 16;
|
int STREAM_HEADER_NONCE_LENGTH = 24;
|
||||||
|
|
||||||
/** The length of the stream header initialisation vector (IV) in bytes. */
|
/** The length of the stream header initialisation vector (IV) in bytes. */
|
||||||
int STREAM_HEADER_IV_LENGTH = 24;
|
int STREAM_HEADER_IV_LENGTH = STREAM_HEADER_NONCE_LENGTH - 8;
|
||||||
|
|
||||||
|
/** The length of the message authentication code (MAC) in bytes. */
|
||||||
|
int MAC_LENGTH = 16;
|
||||||
|
|
||||||
/** The length of the stream header in bytes. */
|
/** The length of the stream header in bytes. */
|
||||||
int STREAM_HEADER_LENGTH = STREAM_HEADER_IV_LENGTH + SecretKey.LENGTH
|
int STREAM_HEADER_LENGTH = STREAM_HEADER_IV_LENGTH + SecretKey.LENGTH
|
||||||
@@ -42,7 +45,8 @@ public interface TransportConstants {
|
|||||||
* support. Streams may be shorter than this length, but all transport
|
* support. Streams may be shorter than this length, but all transport
|
||||||
* plugins must support streams of at least this length.
|
* plugins must support streams of at least this length.
|
||||||
*/
|
*/
|
||||||
int MIN_STREAM_LENGTH = 64 * 1024; // 64 KiB
|
int MIN_STREAM_LENGTH = STREAM_HEADER_LENGTH + FRAME_HEADER_LENGTH
|
||||||
|
+ MAC_LENGTH;
|
||||||
|
|
||||||
/** The maximum difference in milliseconds between two peers' clocks. */
|
/** The maximum difference in milliseconds between two peers' clocks. */
|
||||||
int MAX_CLOCK_DIFFERENCE = 24 * 60 * 60 * 1000; // 24 hours
|
int MAX_CLOCK_DIFFERENCE = 24 * 60 * 60 * 1000; // 24 hours
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package org.briarproject.crypto;
|
package org.briarproject.crypto;
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Provider;
|
|
||||||
|
|
||||||
import org.briarproject.api.crypto.SecretKey;
|
import org.briarproject.api.crypto.SecretKey;
|
||||||
import org.briarproject.api.crypto.StreamDecrypter;
|
import org.briarproject.api.crypto.StreamDecrypter;
|
||||||
import org.briarproject.api.crypto.StreamDecrypterFactory;
|
import org.briarproject.api.crypto.StreamDecrypterFactory;
|
||||||
import org.briarproject.api.transport.StreamContext;
|
import org.briarproject.api.transport.StreamContext;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Provider;
|
||||||
|
|
||||||
class StreamDecrypterFactoryImpl implements StreamDecrypterFactory {
|
class StreamDecrypterFactoryImpl implements StreamDecrypterFactory {
|
||||||
|
|
||||||
private final Provider<AuthenticatedCipher> cipherProvider;
|
private final Provider<AuthenticatedCipher> cipherProvider;
|
||||||
@@ -19,14 +19,17 @@ class StreamDecrypterFactoryImpl implements StreamDecrypterFactory {
|
|||||||
this.cipherProvider = cipherProvider;
|
this.cipherProvider = cipherProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public StreamDecrypter createStreamDecrypter(InputStream in,
|
public StreamDecrypter createStreamDecrypter(InputStream in,
|
||||||
StreamContext ctx) {
|
StreamContext ctx) {
|
||||||
AuthenticatedCipher cipher = cipherProvider.get();
|
AuthenticatedCipher cipher = cipherProvider.get();
|
||||||
return new StreamDecrypterImpl(in, cipher, ctx.getHeaderKey());
|
return new StreamDecrypterImpl(in, cipher, ctx.getStreamNumber(),
|
||||||
|
ctx.getHeaderKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public StreamDecrypter createInvitationStreamDecrypter(InputStream in,
|
public StreamDecrypter createInvitationStreamDecrypter(InputStream in,
|
||||||
SecretKey headerKey) {
|
SecretKey headerKey) {
|
||||||
return new StreamDecrypterImpl(in, cipherProvider.get(), headerKey);
|
return new StreamDecrypterImpl(in, cipherProvider.get(), 0, headerKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package org.briarproject.crypto;
|
|||||||
import org.briarproject.api.FormatException;
|
import org.briarproject.api.FormatException;
|
||||||
import org.briarproject.api.crypto.SecretKey;
|
import org.briarproject.api.crypto.SecretKey;
|
||||||
import org.briarproject.api.crypto.StreamDecrypter;
|
import org.briarproject.api.crypto.StreamDecrypter;
|
||||||
|
import org.briarproject.util.ByteUtils;
|
||||||
|
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -17,11 +18,14 @@ import static org.briarproject.api.transport.TransportConstants.MAX_FRAME_LENGTH
|
|||||||
import static org.briarproject.api.transport.TransportConstants.MAX_PAYLOAD_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.briarproject.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
|
||||||
import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
|
import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
|
||||||
|
import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_NONCE_LENGTH;
|
||||||
|
import static org.briarproject.util.ByteUtils.INT_64_BYTES;
|
||||||
|
|
||||||
class StreamDecrypterImpl implements StreamDecrypter {
|
class StreamDecrypterImpl implements StreamDecrypter {
|
||||||
|
|
||||||
private final InputStream in;
|
private final InputStream in;
|
||||||
private final AuthenticatedCipher cipher;
|
private final AuthenticatedCipher cipher;
|
||||||
|
private final long streamNumber;
|
||||||
private final SecretKey streamHeaderKey;
|
private final SecretKey streamHeaderKey;
|
||||||
private final byte[] frameNonce, frameHeader, frameCiphertext;
|
private final byte[] frameNonce, frameHeader, frameCiphertext;
|
||||||
|
|
||||||
@@ -30,9 +34,10 @@ class StreamDecrypterImpl implements StreamDecrypter {
|
|||||||
private boolean finalFrame;
|
private boolean finalFrame;
|
||||||
|
|
||||||
StreamDecrypterImpl(InputStream in, AuthenticatedCipher cipher,
|
StreamDecrypterImpl(InputStream in, AuthenticatedCipher cipher,
|
||||||
SecretKey streamHeaderKey) {
|
long streamNumber, SecretKey streamHeaderKey) {
|
||||||
this.in = in;
|
this.in = in;
|
||||||
this.cipher = cipher;
|
this.cipher = cipher;
|
||||||
|
this.streamNumber = streamNumber;
|
||||||
this.streamHeaderKey = streamHeaderKey;
|
this.streamHeaderKey = streamHeaderKey;
|
||||||
frameNonce = new byte[FRAME_NONCE_LENGTH];
|
frameNonce = new byte[FRAME_NONCE_LENGTH];
|
||||||
frameHeader = new byte[FRAME_HEADER_PLAINTEXT_LENGTH];
|
frameHeader = new byte[FRAME_HEADER_PLAINTEXT_LENGTH];
|
||||||
@@ -42,6 +47,7 @@ class StreamDecrypterImpl implements StreamDecrypter {
|
|||||||
finalFrame = false;
|
finalFrame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int readFrame(byte[] payload) throws IOException {
|
public int readFrame(byte[] payload) throws IOException {
|
||||||
// The buffer must be big enough for a full-size frame
|
// The buffer must be big enough for a full-size frame
|
||||||
if (payload.length < MAX_PAYLOAD_LENGTH)
|
if (payload.length < MAX_PAYLOAD_LENGTH)
|
||||||
@@ -103,7 +109,6 @@ class StreamDecrypterImpl implements StreamDecrypter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void readStreamHeader() throws IOException {
|
private void readStreamHeader() throws IOException {
|
||||||
byte[] streamHeaderIv = new byte[STREAM_HEADER_IV_LENGTH];
|
|
||||||
byte[] streamHeaderCiphertext = new byte[STREAM_HEADER_LENGTH];
|
byte[] streamHeaderCiphertext = new byte[STREAM_HEADER_LENGTH];
|
||||||
byte[] streamHeaderPlaintext = new byte[SecretKey.LENGTH];
|
byte[] streamHeaderPlaintext = new byte[SecretKey.LENGTH];
|
||||||
// Read the stream header
|
// Read the stream header
|
||||||
@@ -114,11 +119,14 @@ class StreamDecrypterImpl implements StreamDecrypter {
|
|||||||
if (read == -1) throw new EOFException();
|
if (read == -1) throw new EOFException();
|
||||||
offset += read;
|
offset += read;
|
||||||
}
|
}
|
||||||
|
// The nonce consists of the stream number followed by the IV
|
||||||
|
byte[] streamHeaderNonce = new byte[STREAM_HEADER_NONCE_LENGTH];
|
||||||
|
ByteUtils.writeUint64(streamNumber, streamHeaderNonce, 0);
|
||||||
|
System.arraycopy(streamHeaderCiphertext, 0, streamHeaderNonce,
|
||||||
|
INT_64_BYTES, STREAM_HEADER_IV_LENGTH);
|
||||||
// Decrypt and authenticate the stream header
|
// Decrypt and authenticate the stream header
|
||||||
System.arraycopy(streamHeaderCiphertext, 0, streamHeaderIv, 0,
|
|
||||||
STREAM_HEADER_IV_LENGTH);
|
|
||||||
try {
|
try {
|
||||||
cipher.init(false, streamHeaderKey, streamHeaderIv);
|
cipher.init(false, streamHeaderKey, streamHeaderNonce);
|
||||||
int decrypted = cipher.process(streamHeaderCiphertext,
|
int decrypted = cipher.process(streamHeaderCiphertext,
|
||||||
STREAM_HEADER_IV_LENGTH, SecretKey.LENGTH + MAC_LENGTH,
|
STREAM_HEADER_IV_LENGTH, SecretKey.LENGTH + MAC_LENGTH,
|
||||||
streamHeaderPlaintext, 0);
|
streamHeaderPlaintext, 0);
|
||||||
|
|||||||
@@ -26,25 +26,28 @@ class StreamEncrypterFactoryImpl implements StreamEncrypterFactory {
|
|||||||
this.cipherProvider = cipherProvider;
|
this.cipherProvider = cipherProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public StreamEncrypter createStreamEncrypter(OutputStream out,
|
public StreamEncrypter createStreamEncrypter(OutputStream out,
|
||||||
StreamContext ctx) {
|
StreamContext ctx) {
|
||||||
AuthenticatedCipher cipher = cipherProvider.get();
|
AuthenticatedCipher cipher = cipherProvider.get();
|
||||||
|
long streamNumber = ctx.getStreamNumber();
|
||||||
byte[] tag = new byte[TAG_LENGTH];
|
byte[] tag = new byte[TAG_LENGTH];
|
||||||
crypto.encodeTag(tag, ctx.getTagKey(), ctx.getStreamNumber());
|
crypto.encodeTag(tag, ctx.getTagKey(), streamNumber);
|
||||||
byte[] streamHeaderIv = new byte[STREAM_HEADER_IV_LENGTH];
|
byte[] streamHeaderIv = new byte[STREAM_HEADER_IV_LENGTH];
|
||||||
crypto.getSecureRandom().nextBytes(streamHeaderIv);
|
crypto.getSecureRandom().nextBytes(streamHeaderIv);
|
||||||
SecretKey frameKey = crypto.generateSecretKey();
|
SecretKey frameKey = crypto.generateSecretKey();
|
||||||
return new StreamEncrypterImpl(out, cipher, tag, streamHeaderIv,
|
return new StreamEncrypterImpl(out, cipher, streamNumber, tag,
|
||||||
ctx.getHeaderKey(), frameKey);
|
streamHeaderIv, ctx.getHeaderKey(), frameKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public StreamEncrypter createInvitationStreamEncrypter(OutputStream out,
|
public StreamEncrypter createInvitationStreamEncrypter(OutputStream out,
|
||||||
SecretKey headerKey) {
|
SecretKey headerKey) {
|
||||||
AuthenticatedCipher cipher = cipherProvider.get();
|
AuthenticatedCipher cipher = cipherProvider.get();
|
||||||
byte[] streamHeaderIv = new byte[STREAM_HEADER_IV_LENGTH];
|
byte[] streamHeaderIv = new byte[STREAM_HEADER_IV_LENGTH];
|
||||||
crypto.getSecureRandom().nextBytes(streamHeaderIv);
|
crypto.getSecureRandom().nextBytes(streamHeaderIv);
|
||||||
SecretKey frameKey = crypto.generateSecretKey();
|
SecretKey frameKey = crypto.generateSecretKey();
|
||||||
return new StreamEncrypterImpl(out, cipher, null, streamHeaderIv,
|
return new StreamEncrypterImpl(out, cipher, 0, null, streamHeaderIv,
|
||||||
headerKey, frameKey);
|
headerKey, frameKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package org.briarproject.crypto;
|
|||||||
|
|
||||||
import org.briarproject.api.crypto.SecretKey;
|
import org.briarproject.api.crypto.SecretKey;
|
||||||
import org.briarproject.api.crypto.StreamEncrypter;
|
import org.briarproject.api.crypto.StreamEncrypter;
|
||||||
|
import org.briarproject.util.ByteUtils;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@@ -15,23 +17,28 @@ import static org.briarproject.api.transport.TransportConstants.MAX_FRAME_LENGTH
|
|||||||
import static org.briarproject.api.transport.TransportConstants.MAX_PAYLOAD_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.briarproject.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
|
||||||
import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
|
import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
|
||||||
|
import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_NONCE_LENGTH;
|
||||||
|
import static org.briarproject.util.ByteUtils.INT_64_BYTES;
|
||||||
|
|
||||||
class StreamEncrypterImpl implements StreamEncrypter {
|
class StreamEncrypterImpl implements StreamEncrypter {
|
||||||
|
|
||||||
private final OutputStream out;
|
private final OutputStream out;
|
||||||
private final AuthenticatedCipher cipher;
|
private final AuthenticatedCipher cipher;
|
||||||
private final SecretKey streamHeaderKey, frameKey;
|
private final SecretKey streamHeaderKey, frameKey;
|
||||||
|
private final long streamNumber;
|
||||||
private final byte[] tag, streamHeaderIv;
|
private final byte[] tag, streamHeaderIv;
|
||||||
private final byte[] frameNonce, frameHeader, framePlaintext, frameCiphertext;
|
private final byte[] frameNonce, frameHeader;
|
||||||
|
private final byte[] framePlaintext, frameCiphertext;
|
||||||
|
|
||||||
private long frameNumber;
|
private long frameNumber;
|
||||||
private boolean writeTag, writeStreamHeader;
|
private boolean writeTag, writeStreamHeader;
|
||||||
|
|
||||||
StreamEncrypterImpl(OutputStream out, AuthenticatedCipher cipher,
|
StreamEncrypterImpl(OutputStream out, AuthenticatedCipher cipher,
|
||||||
byte[] tag, byte[] streamHeaderIv, SecretKey streamHeaderKey,
|
long streamNumber, @Nullable byte[] tag, byte[] streamHeaderIv,
|
||||||
SecretKey frameKey) {
|
SecretKey streamHeaderKey, SecretKey frameKey) {
|
||||||
this.out = out;
|
this.out = out;
|
||||||
this.cipher = cipher;
|
this.cipher = cipher;
|
||||||
|
this.streamNumber = streamNumber;
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
this.streamHeaderIv = streamHeaderIv;
|
this.streamHeaderIv = streamHeaderIv;
|
||||||
this.streamHeaderKey = streamHeaderKey;
|
this.streamHeaderKey = streamHeaderKey;
|
||||||
@@ -45,6 +52,7 @@ class StreamEncrypterImpl implements StreamEncrypter {
|
|||||||
writeStreamHeader = true;
|
writeStreamHeader = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void writeFrame(byte[] payload, int payloadLength,
|
public void writeFrame(byte[] payload, int payloadLength,
|
||||||
int paddingLength, boolean finalFrame) throws IOException {
|
int paddingLength, boolean finalFrame) throws IOException {
|
||||||
if (payloadLength + paddingLength > MAX_PAYLOAD_LENGTH)
|
if (payloadLength + paddingLength > MAX_PAYLOAD_LENGTH)
|
||||||
@@ -91,18 +99,24 @@ class StreamEncrypterImpl implements StreamEncrypter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void writeTag() throws IOException {
|
private void writeTag() throws IOException {
|
||||||
|
if (tag == null) throw new IllegalStateException();
|
||||||
out.write(tag, 0, tag.length);
|
out.write(tag, 0, tag.length);
|
||||||
writeTag = false;
|
writeTag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeStreamHeader() throws IOException {
|
private void writeStreamHeader() throws IOException {
|
||||||
|
// The nonce consists of the stream number followed by the IV
|
||||||
|
byte[] streamHeaderNonce = new byte[STREAM_HEADER_NONCE_LENGTH];
|
||||||
|
ByteUtils.writeUint64(streamNumber, streamHeaderNonce, 0);
|
||||||
|
System.arraycopy(streamHeaderIv, 0, streamHeaderNonce, INT_64_BYTES,
|
||||||
|
STREAM_HEADER_IV_LENGTH);
|
||||||
byte[] streamHeaderPlaintext = frameKey.getBytes();
|
byte[] streamHeaderPlaintext = frameKey.getBytes();
|
||||||
byte[] streamHeaderCiphertext = new byte[STREAM_HEADER_LENGTH];
|
byte[] streamHeaderCiphertext = new byte[STREAM_HEADER_LENGTH];
|
||||||
System.arraycopy(streamHeaderIv, 0, streamHeaderCiphertext, 0,
|
System.arraycopy(streamHeaderIv, 0, streamHeaderCiphertext, 0,
|
||||||
STREAM_HEADER_IV_LENGTH);
|
STREAM_HEADER_IV_LENGTH);
|
||||||
// Encrypt and authenticate the frame key
|
// Encrypt and authenticate the frame key
|
||||||
try {
|
try {
|
||||||
cipher.init(true, streamHeaderKey, streamHeaderIv);
|
cipher.init(true, streamHeaderKey, streamHeaderNonce);
|
||||||
int encrypted = cipher.process(streamHeaderPlaintext, 0,
|
int encrypted = cipher.process(streamHeaderPlaintext, 0,
|
||||||
SecretKey.LENGTH, streamHeaderCiphertext,
|
SecretKey.LENGTH, streamHeaderCiphertext,
|
||||||
STREAM_HEADER_IV_LENGTH);
|
STREAM_HEADER_IV_LENGTH);
|
||||||
@@ -115,6 +129,7 @@ class StreamEncrypterImpl implements StreamEncrypter {
|
|||||||
writeStreamHeader = false;
|
writeStreamHeader = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void flush() throws IOException {
|
public void flush() throws IOException {
|
||||||
// Write the tag if required
|
// Write the tag if required
|
||||||
if (writeTag) writeTag();
|
if (writeTag) writeTag();
|
||||||
|
|||||||
@@ -22,22 +22,23 @@ public class StreamDecrypterImplTest extends BriarTestCase {
|
|||||||
|
|
||||||
private final AuthenticatedCipher cipher;
|
private final AuthenticatedCipher cipher;
|
||||||
private final SecretKey streamHeaderKey, frameKey;
|
private final SecretKey streamHeaderKey, frameKey;
|
||||||
private final byte[] streamHeaderIv;
|
private final byte[] streamHeaderIv, payload;
|
||||||
|
private final int payloadLength = 123, paddingLength = 234;
|
||||||
|
private final long streamNumber = 1234;
|
||||||
|
|
||||||
public StreamDecrypterImplTest() {
|
public StreamDecrypterImplTest() {
|
||||||
cipher = new TestAuthenticatedCipher(); // Null cipher
|
cipher = new TestAuthenticatedCipher(); // Null cipher
|
||||||
streamHeaderKey = TestUtils.getSecretKey();
|
streamHeaderKey = TestUtils.getSecretKey();
|
||||||
frameKey = TestUtils.getSecretKey();
|
frameKey = TestUtils.getSecretKey();
|
||||||
streamHeaderIv = TestUtils.getRandomBytes(STREAM_HEADER_IV_LENGTH);
|
streamHeaderIv = TestUtils.getRandomBytes(STREAM_HEADER_IV_LENGTH);
|
||||||
|
payload = TestUtils.getRandomBytes(payloadLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadValidFrames() throws Exception {
|
public void testReadValidFrames() throws Exception {
|
||||||
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
|
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
|
||||||
int payloadLength = 123, paddingLength = 234;
|
|
||||||
FrameEncoder.encodeHeader(frameHeader, false, payloadLength,
|
FrameEncoder.encodeHeader(frameHeader, false, payloadLength,
|
||||||
paddingLength);
|
paddingLength);
|
||||||
byte[] payload = TestUtils.getRandomBytes(payloadLength);
|
|
||||||
|
|
||||||
byte[] frameHeader1 = new byte[FRAME_HEADER_LENGTH];
|
byte[] frameHeader1 = new byte[FRAME_HEADER_LENGTH];
|
||||||
int payloadLength1 = 345, paddingLength1 = 456;
|
int payloadLength1 = 345, paddingLength1 = 456;
|
||||||
@@ -60,7 +61,7 @@ public class StreamDecrypterImplTest extends BriarTestCase {
|
|||||||
|
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||||
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
|
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
|
||||||
streamHeaderKey);
|
streamNumber, streamHeaderKey);
|
||||||
|
|
||||||
// Read the first frame
|
// Read the first frame
|
||||||
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
|
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
|
||||||
@@ -78,10 +79,9 @@ public class StreamDecrypterImplTest extends BriarTestCase {
|
|||||||
@Test(expected = IOException.class)
|
@Test(expected = IOException.class)
|
||||||
public void testTruncatedFrameThrowsException() throws Exception {
|
public void testTruncatedFrameThrowsException() throws Exception {
|
||||||
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
|
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
|
||||||
int payloadLength = 123, paddingLength = 234;
|
|
||||||
FrameEncoder.encodeHeader(frameHeader, false, payloadLength,
|
FrameEncoder.encodeHeader(frameHeader, false, payloadLength,
|
||||||
paddingLength);
|
paddingLength);
|
||||||
byte[] payload = TestUtils.getRandomBytes(payloadLength);
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
out.write(streamHeaderIv);
|
out.write(streamHeaderIv);
|
||||||
out.write(frameKey.getBytes());
|
out.write(frameKey.getBytes());
|
||||||
@@ -93,7 +93,7 @@ public class StreamDecrypterImplTest extends BriarTestCase {
|
|||||||
|
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||||
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
|
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
|
||||||
streamHeaderKey);
|
streamNumber, streamHeaderKey);
|
||||||
|
|
||||||
// Try to read the truncated frame
|
// Try to read the truncated frame
|
||||||
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
|
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
|
||||||
@@ -121,7 +121,7 @@ public class StreamDecrypterImplTest extends BriarTestCase {
|
|||||||
|
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||||
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
|
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
|
||||||
streamHeaderKey);
|
streamNumber, streamHeaderKey);
|
||||||
|
|
||||||
// Try to read the invalid frame
|
// Try to read the invalid frame
|
||||||
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
|
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
|
||||||
@@ -131,10 +131,8 @@ public class StreamDecrypterImplTest extends BriarTestCase {
|
|||||||
@Test(expected = IOException.class)
|
@Test(expected = IOException.class)
|
||||||
public void testNonZeroPaddingThrowsException() throws Exception {
|
public void testNonZeroPaddingThrowsException() throws Exception {
|
||||||
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
|
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
|
||||||
int payloadLength = 123, paddingLength = 234;
|
|
||||||
FrameEncoder.encodeHeader(frameHeader, false, payloadLength,
|
FrameEncoder.encodeHeader(frameHeader, false, payloadLength,
|
||||||
paddingLength);
|
paddingLength);
|
||||||
byte[] payload = TestUtils.getRandomBytes(payloadLength);
|
|
||||||
// Set one of the padding bytes non-zero
|
// Set one of the padding bytes non-zero
|
||||||
byte[] padding = new byte[paddingLength];
|
byte[] padding = new byte[paddingLength];
|
||||||
padding[paddingLength - 1] = 1;
|
padding[paddingLength - 1] = 1;
|
||||||
@@ -150,7 +148,7 @@ public class StreamDecrypterImplTest extends BriarTestCase {
|
|||||||
|
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||||
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
|
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
|
||||||
streamHeaderKey);
|
streamNumber, streamHeaderKey);
|
||||||
|
|
||||||
// Try to read the invalid frame
|
// Try to read the invalid frame
|
||||||
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
|
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
|
||||||
@@ -160,10 +158,8 @@ public class StreamDecrypterImplTest extends BriarTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testCannotReadBeyondFinalFrame() throws Exception {
|
public void testCannotReadBeyondFinalFrame() throws Exception {
|
||||||
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
|
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
|
||||||
int payloadLength = 123, paddingLength = 234;
|
|
||||||
FrameEncoder.encodeHeader(frameHeader, true, payloadLength,
|
FrameEncoder.encodeHeader(frameHeader, true, payloadLength,
|
||||||
paddingLength);
|
paddingLength);
|
||||||
byte[] payload = TestUtils.getRandomBytes(payloadLength);
|
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
out.write(streamHeaderIv);
|
out.write(streamHeaderIv);
|
||||||
@@ -178,7 +174,7 @@ public class StreamDecrypterImplTest extends BriarTestCase {
|
|||||||
|
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||||
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
|
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
|
||||||
streamHeaderKey);
|
streamNumber, streamHeaderKey);
|
||||||
|
|
||||||
// Read the first frame
|
// Read the first frame
|
||||||
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
|
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ public class StreamEncrypterImplTest extends BriarTestCase {
|
|||||||
|
|
||||||
private final AuthenticatedCipher cipher;
|
private final AuthenticatedCipher cipher;
|
||||||
private final SecretKey streamHeaderKey, frameKey;
|
private final SecretKey streamHeaderKey, frameKey;
|
||||||
private final byte[] tag, streamHeaderIv;
|
private final byte[] tag, streamHeaderIv, payload;
|
||||||
|
private final long streamNumber = 1234;
|
||||||
|
private final int payloadLength = 123, paddingLength = 234;
|
||||||
|
|
||||||
public StreamEncrypterImplTest() {
|
public StreamEncrypterImplTest() {
|
||||||
cipher = new TestAuthenticatedCipher(); // Null cipher
|
cipher = new TestAuthenticatedCipher(); // Null cipher
|
||||||
@@ -25,15 +27,14 @@ public class StreamEncrypterImplTest extends BriarTestCase {
|
|||||||
frameKey = TestUtils.getSecretKey();
|
frameKey = TestUtils.getSecretKey();
|
||||||
tag = TestUtils.getRandomBytes(TAG_LENGTH);
|
tag = TestUtils.getRandomBytes(TAG_LENGTH);
|
||||||
streamHeaderIv = TestUtils.getRandomBytes(STREAM_HEADER_IV_LENGTH);
|
streamHeaderIv = TestUtils.getRandomBytes(STREAM_HEADER_IV_LENGTH);
|
||||||
|
payload = TestUtils.getRandomBytes(payloadLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWriteUnpaddedNonFinalFrameWithTag() throws Exception {
|
public void testWriteUnpaddedNonFinalFrameWithTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, tag,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
||||||
int payloadLength = 123;
|
|
||||||
byte[] payload = TestUtils.getRandomBytes(payloadLength);
|
|
||||||
|
|
||||||
s.writeFrame(payload, payloadLength, 0, false);
|
s.writeFrame(payload, payloadLength, 0, false);
|
||||||
|
|
||||||
@@ -55,10 +56,8 @@ public class StreamEncrypterImplTest extends BriarTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testWriteUnpaddedFinalFrameWithTag() throws Exception {
|
public void testWriteUnpaddedFinalFrameWithTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, tag,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
||||||
int payloadLength = 123;
|
|
||||||
byte[] payload = TestUtils.getRandomBytes(payloadLength);
|
|
||||||
|
|
||||||
s.writeFrame(payload, payloadLength, 0, true);
|
s.writeFrame(payload, payloadLength, 0, true);
|
||||||
|
|
||||||
@@ -80,10 +79,8 @@ public class StreamEncrypterImplTest extends BriarTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testWriteUnpaddedNonFinalFrameWithoutTag() throws Exception {
|
public void testWriteUnpaddedNonFinalFrameWithoutTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, null,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, null, streamHeaderIv, streamHeaderKey, frameKey);
|
||||||
int payloadLength = 123;
|
|
||||||
byte[] payload = TestUtils.getRandomBytes(payloadLength);
|
|
||||||
|
|
||||||
s.writeFrame(payload, payloadLength, 0, false);
|
s.writeFrame(payload, payloadLength, 0, false);
|
||||||
|
|
||||||
@@ -104,10 +101,8 @@ public class StreamEncrypterImplTest extends BriarTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testWriteUnpaddedFinalFrameWithoutTag() throws Exception {
|
public void testWriteUnpaddedFinalFrameWithoutTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, null,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, null, streamHeaderIv, streamHeaderKey, frameKey);
|
||||||
int payloadLength = 123;
|
|
||||||
byte[] payload = TestUtils.getRandomBytes(payloadLength);
|
|
||||||
|
|
||||||
s.writeFrame(payload, payloadLength, 0, true);
|
s.writeFrame(payload, payloadLength, 0, true);
|
||||||
|
|
||||||
@@ -128,10 +123,8 @@ public class StreamEncrypterImplTest extends BriarTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testWritePaddedNonFinalFrameWithTag() throws Exception {
|
public void testWritePaddedNonFinalFrameWithTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, tag,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
||||||
int payloadLength = 123, paddingLength = 234;
|
|
||||||
byte[] payload = TestUtils.getRandomBytes(payloadLength);
|
|
||||||
|
|
||||||
s.writeFrame(payload, payloadLength, paddingLength, false);
|
s.writeFrame(payload, payloadLength, paddingLength, false);
|
||||||
|
|
||||||
@@ -155,10 +148,8 @@ public class StreamEncrypterImplTest extends BriarTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testWritePaddedFinalFrameWithTag() throws Exception {
|
public void testWritePaddedFinalFrameWithTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, tag,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
||||||
int payloadLength = 123, paddingLength = 234;
|
|
||||||
byte[] payload = TestUtils.getRandomBytes(payloadLength);
|
|
||||||
|
|
||||||
s.writeFrame(payload, payloadLength, paddingLength, true);
|
s.writeFrame(payload, payloadLength, paddingLength, true);
|
||||||
|
|
||||||
@@ -182,10 +173,8 @@ public class StreamEncrypterImplTest extends BriarTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testWritePaddedNonFinalFrameWithoutTag() throws Exception {
|
public void testWritePaddedNonFinalFrameWithoutTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, null,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, null, streamHeaderIv, streamHeaderKey, frameKey);
|
||||||
int payloadLength = 123, paddingLength = 234;
|
|
||||||
byte[] payload = TestUtils.getRandomBytes(payloadLength);
|
|
||||||
|
|
||||||
s.writeFrame(payload, payloadLength, paddingLength, false);
|
s.writeFrame(payload, payloadLength, paddingLength, false);
|
||||||
|
|
||||||
@@ -208,10 +197,8 @@ public class StreamEncrypterImplTest extends BriarTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testWritePaddedFinalFrameWithoutTag() throws Exception {
|
public void testWritePaddedFinalFrameWithoutTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, null,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, null, streamHeaderIv, streamHeaderKey, frameKey);
|
||||||
int payloadLength = 123, paddingLength = 234;
|
|
||||||
byte[] payload = TestUtils.getRandomBytes(payloadLength);
|
|
||||||
|
|
||||||
s.writeFrame(payload, payloadLength, paddingLength, true);
|
s.writeFrame(payload, payloadLength, paddingLength, true);
|
||||||
|
|
||||||
@@ -234,10 +221,8 @@ public class StreamEncrypterImplTest extends BriarTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testWriteTwoFramesWithTag() throws Exception {
|
public void testWriteTwoFramesWithTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, tag,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
||||||
int payloadLength = 123, paddingLength = 234;
|
|
||||||
byte[] payload = TestUtils.getRandomBytes(payloadLength);
|
|
||||||
int payloadLength1 = 345, paddingLength1 = 456;
|
int payloadLength1 = 345, paddingLength1 = 456;
|
||||||
byte[] payload1 = TestUtils.getRandomBytes(payloadLength1);
|
byte[] payload1 = TestUtils.getRandomBytes(payloadLength1);
|
||||||
|
|
||||||
@@ -273,8 +258,8 @@ public class StreamEncrypterImplTest extends BriarTestCase {
|
|||||||
public void testFlushWritesTagAndStreamHeaderIfNotAlreadyWritten()
|
public void testFlushWritesTagAndStreamHeaderIfNotAlreadyWritten()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, tag,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
||||||
|
|
||||||
// Flush the stream once
|
// Flush the stream once
|
||||||
s.flush();
|
s.flush();
|
||||||
@@ -293,8 +278,8 @@ public class StreamEncrypterImplTest extends BriarTestCase {
|
|||||||
public void testFlushDoesNotWriteTagOrStreamHeaderIfAlreadyWritten()
|
public void testFlushDoesNotWriteTagOrStreamHeaderIfAlreadyWritten()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, tag,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
||||||
|
|
||||||
// Flush the stream twice
|
// Flush the stream twice
|
||||||
s.flush();
|
s.flush();
|
||||||
@@ -313,8 +298,8 @@ public class StreamEncrypterImplTest extends BriarTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testFlushDoesNotWriteTagIfNull() throws Exception {
|
public void testFlushDoesNotWriteTagIfNull() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, null,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, null, streamHeaderIv, streamHeaderKey, frameKey);
|
||||||
|
|
||||||
// Flush the stream once
|
// Flush the stream once
|
||||||
s.flush();
|
s.flush();
|
||||||
|
|||||||
Reference in New Issue
Block a user