mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 06:09:55 +01:00
Added optional padding to the frame format, so transports that are
vulnerable to traffic analysis can frame their data independently of packet boundaries.
This commit is contained in:
@@ -31,8 +31,8 @@ implements ConnectionReader {
|
|||||||
super(decrypter.getInputStream());
|
super(decrypter.getInputStream());
|
||||||
this.decrypter = decrypter;
|
this.decrypter = decrypter;
|
||||||
this.mac = mac;
|
this.mac = mac;
|
||||||
maxPayloadLength = MAX_FRAME_LENGTH - 6 - mac.getMacLength();
|
maxPayloadLength = MAX_FRAME_LENGTH - 8 - mac.getMacLength();
|
||||||
header = new byte[6];
|
header = new byte[8];
|
||||||
payload = new byte[maxPayloadLength];
|
payload = new byte[maxPayloadLength];
|
||||||
footer = new byte[mac.getMacLength()];
|
footer = new byte[mac.getMacLength()];
|
||||||
}
|
}
|
||||||
@@ -83,9 +83,11 @@ implements ConnectionReader {
|
|||||||
// Check that the frame has the expected frame number
|
// Check that the frame has the expected frame number
|
||||||
if(ByteUtils.readUint32(header, 0) != frame)
|
if(ByteUtils.readUint32(header, 0) != frame)
|
||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
// Check that the payload length is legal
|
// Check that the payload and padding lengths are legal
|
||||||
payloadLen = ByteUtils.readUint16(header, 4);
|
payloadLen = ByteUtils.readUint16(header, 4);
|
||||||
if(payloadLen == 0 || payloadLen > maxPayloadLength)
|
int paddingLen = ByteUtils.readUint16(header, 6);
|
||||||
|
if(payloadLen + paddingLen == 0) throw new FormatException();
|
||||||
|
if(payloadLen + paddingLen > maxPayloadLength)
|
||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
frame++;
|
frame++;
|
||||||
// Read the payload
|
// Read the payload
|
||||||
@@ -97,6 +99,18 @@ implements ConnectionReader {
|
|||||||
offset += read;
|
offset += read;
|
||||||
}
|
}
|
||||||
payloadOff = 0;
|
payloadOff = 0;
|
||||||
|
// Read the padding
|
||||||
|
while(offset < payloadLen + paddingLen) {
|
||||||
|
int read = in.read(payload, offset,
|
||||||
|
payloadLen + paddingLen - offset);
|
||||||
|
if(read == -1) throw new EOFException(); // Unexpected EOF
|
||||||
|
mac.update(payload, offset, read);
|
||||||
|
offset += read;
|
||||||
|
}
|
||||||
|
// Check that the padding is all zeroes
|
||||||
|
for(int i = payloadLen; i < payloadLen + paddingLen; i++) {
|
||||||
|
if(payload[i] != 0) throw new FormatException();
|
||||||
|
}
|
||||||
// Read the MAC
|
// Read the MAC
|
||||||
byte[] expectedMac = mac.doFinal();
|
byte[] expectedMac = mac.doFinal();
|
||||||
decrypter.readMac(footer);
|
decrypter.readMac(footer);
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ implements ConnectionWriter {
|
|||||||
super(encrypter.getOutputStream());
|
super(encrypter.getOutputStream());
|
||||||
this.encrypter = encrypter;
|
this.encrypter = encrypter;
|
||||||
this.mac = mac;
|
this.mac = mac;
|
||||||
maxPayloadLength = MAX_FRAME_LENGTH - 6 - mac.getMacLength();
|
maxPayloadLength = MAX_FRAME_LENGTH - 8 - mac.getMacLength();
|
||||||
buf = new ByteArrayOutputStream(maxPayloadLength);
|
buf = new ByteArrayOutputStream(maxPayloadLength);
|
||||||
header = new byte[6];
|
header = new byte[8];
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutputStream getOutputStream() {
|
public OutputStream getOutputStream() {
|
||||||
|
|||||||
@@ -31,7 +31,6 @@
|
|||||||
<test name='net.sf.briar.protocol.ConsumersTest'/>
|
<test name='net.sf.briar.protocol.ConsumersTest'/>
|
||||||
<test name='net.sf.briar.protocol.ProtocolReadWriteTest'/>
|
<test name='net.sf.briar.protocol.ProtocolReadWriteTest'/>
|
||||||
<test name='net.sf.briar.protocol.RequestReaderTest'/>
|
<test name='net.sf.briar.protocol.RequestReaderTest'/>
|
||||||
<test name='net.sf.briar.protocol.SigningDigestingOutputStreamTest'/>
|
|
||||||
<test name='net.sf.briar.protocol.writers.RequestWriterImplTest'/>
|
<test name='net.sf.briar.protocol.writers.RequestWriterImplTest'/>
|
||||||
<test name='net.sf.briar.serial.ReaderImplTest'/>
|
<test name='net.sf.briar.serial.ReaderImplTest'/>
|
||||||
<test name='net.sf.briar.serial.WriterImplTest'/>
|
<test name='net.sf.briar.serial.WriterImplTest'/>
|
||||||
|
|||||||
@@ -173,8 +173,7 @@ public class FileReadWriteTest extends TestCase {
|
|||||||
TransportWriter t = protocolWriterFactory.createTransportWriter(out);
|
TransportWriter t = protocolWriterFactory.createTransportWriter(out);
|
||||||
t.writeTransports(transports, timestamp);
|
t.writeTransports(transports, timestamp);
|
||||||
|
|
||||||
w.getOutputStream().flush();
|
out.close();
|
||||||
w.getOutputStream().close();
|
|
||||||
assertTrue(file.exists());
|
assertTrue(file.exists());
|
||||||
assertTrue(file.length() > message.getSize());
|
assertTrue(file.length() > message.getSize());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import com.google.inject.Injector;
|
|||||||
public class ConnectionReaderImplTest extends TestCase {
|
public class ConnectionReaderImplTest extends TestCase {
|
||||||
|
|
||||||
private final Mac mac;
|
private final Mac mac;
|
||||||
|
private final int headerLength = 8, macLength;
|
||||||
|
|
||||||
public ConnectionReaderImplTest() throws Exception {
|
public ConnectionReaderImplTest() throws Exception {
|
||||||
super();
|
super();
|
||||||
@@ -34,15 +35,17 @@ public class ConnectionReaderImplTest extends TestCase {
|
|||||||
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
||||||
mac = crypto.getMac();
|
mac = crypto.getMac();
|
||||||
mac.init(crypto.generateSecretKey());
|
mac.init(crypto.generateSecretKey());
|
||||||
|
macLength = mac.getMacLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLengthZero() throws Exception {
|
public void testLengthZero() throws Exception {
|
||||||
// Six bytes for the header, none for the payload
|
int payloadLength = 0;
|
||||||
byte[] frame = new byte[6 + mac.getMacLength()];
|
byte[] frame = new byte[headerLength + payloadLength + macLength];
|
||||||
|
writeHeader(frame, 0L, payloadLength, 0);
|
||||||
// Calculate the MAC
|
// Calculate the MAC
|
||||||
mac.update(frame, 0, 6);
|
mac.update(frame, 0, headerLength + payloadLength);
|
||||||
mac.doFinal(frame, 6);
|
mac.doFinal(frame, headerLength + payloadLength);
|
||||||
// Read the frame
|
// Read the frame
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(frame);
|
ByteArrayInputStream in = new ByteArrayInputStream(frame);
|
||||||
ConnectionDecrypter d = new NullConnectionDecrypter(in);
|
ConnectionDecrypter d = new NullConnectionDecrypter(in);
|
||||||
@@ -55,12 +58,12 @@ public class ConnectionReaderImplTest extends TestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLengthOne() throws Exception {
|
public void testLengthOne() throws Exception {
|
||||||
// Six bytes for the header, one for the payload
|
int payloadLength = 1;
|
||||||
byte[] frame = new byte[6 + 1 + mac.getMacLength()];
|
byte[] frame = new byte[headerLength + payloadLength + macLength];
|
||||||
ByteUtils.writeUint16(1, frame, 4); // Frame number 0, length 1
|
writeHeader(frame, 0L, payloadLength, 0);
|
||||||
// Calculate the MAC
|
// Calculate the MAC
|
||||||
mac.update(frame, 0, 6 + 1);
|
mac.update(frame, 0, headerLength + payloadLength);
|
||||||
mac.doFinal(frame, 6 + 1);
|
mac.doFinal(frame, headerLength + payloadLength);
|
||||||
// Read the frame
|
// Read the frame
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(frame);
|
ByteArrayInputStream in = new ByteArrayInputStream(frame);
|
||||||
ConnectionDecrypter d = new NullConnectionDecrypter(in);
|
ConnectionDecrypter d = new NullConnectionDecrypter(in);
|
||||||
@@ -72,18 +75,17 @@ public class ConnectionReaderImplTest extends TestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMaxLength() throws Exception {
|
public void testMaxLength() throws Exception {
|
||||||
int maxPayloadLength = MAX_FRAME_LENGTH - 6 - mac.getMacLength();
|
int maxPayloadLength = MAX_FRAME_LENGTH - headerLength - macLength;
|
||||||
// First frame: max payload length
|
// First frame: max payload length
|
||||||
byte[] frame = new byte[6 + maxPayloadLength + mac.getMacLength()];
|
byte[] frame = new byte[MAX_FRAME_LENGTH];
|
||||||
ByteUtils.writeUint16(maxPayloadLength, frame, 4);
|
writeHeader(frame, 0L, maxPayloadLength, 0);
|
||||||
mac.update(frame, 0, 6 + maxPayloadLength);
|
mac.update(frame, 0, headerLength + maxPayloadLength);
|
||||||
mac.doFinal(frame, 6 + maxPayloadLength);
|
mac.doFinal(frame, headerLength + maxPayloadLength);
|
||||||
// Second frame: max payload length plus one
|
// Second frame: max payload length plus one
|
||||||
byte[] frame1 = new byte[6 + maxPayloadLength + 1 + mac.getMacLength()];
|
byte[] frame1 = new byte[MAX_FRAME_LENGTH + 1];
|
||||||
ByteUtils.writeUint32(1, frame1, 0);
|
writeHeader(frame1, 1L, maxPayloadLength + 1, 0);
|
||||||
ByteUtils.writeUint16(maxPayloadLength + 1, frame1, 4);
|
mac.update(frame1, 0, headerLength + maxPayloadLength + 1);
|
||||||
mac.update(frame1, 0, 6 + maxPayloadLength + 1);
|
mac.doFinal(frame1, headerLength + maxPayloadLength + 1);
|
||||||
mac.doFinal(frame1, 6 + maxPayloadLength + 1);
|
|
||||||
// Concatenate the frames
|
// Concatenate the frames
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
out.write(frame);
|
out.write(frame);
|
||||||
@@ -102,19 +104,51 @@ public class ConnectionReaderImplTest extends TestCase {
|
|||||||
} catch(FormatException expected) {}
|
} catch(FormatException expected) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMaxLengthWithPadding() throws Exception {
|
||||||
|
int maxPayloadLength = MAX_FRAME_LENGTH - headerLength - macLength;
|
||||||
|
int paddingLength = 10;
|
||||||
|
// First frame: max payload length, including padding
|
||||||
|
byte[] frame = new byte[MAX_FRAME_LENGTH];
|
||||||
|
writeHeader(frame, 0L, maxPayloadLength - paddingLength, paddingLength);
|
||||||
|
mac.update(frame, 0, headerLength + maxPayloadLength);
|
||||||
|
mac.doFinal(frame, headerLength + maxPayloadLength);
|
||||||
|
// Second frame: max payload length plus one, including padding
|
||||||
|
byte[] frame1 = new byte[MAX_FRAME_LENGTH + 1];
|
||||||
|
writeHeader(frame1, 1L, maxPayloadLength + 1 - paddingLength,
|
||||||
|
paddingLength);
|
||||||
|
mac.update(frame1, 0, headerLength + maxPayloadLength + 1);
|
||||||
|
mac.doFinal(frame1, headerLength + maxPayloadLength + 1);
|
||||||
|
// Concatenate the frames
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
out.write(frame);
|
||||||
|
out.write(frame1);
|
||||||
|
// Read the first frame
|
||||||
|
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||||
|
ConnectionDecrypter d = new NullConnectionDecrypter(in);
|
||||||
|
ConnectionReader r = new ConnectionReaderImpl(d, mac);
|
||||||
|
byte[] read = new byte[maxPayloadLength - paddingLength];
|
||||||
|
TestUtils.readFully(r.getInputStream(), read);
|
||||||
|
// Try to read the second frame
|
||||||
|
byte[] read1 = new byte[maxPayloadLength + 1 - paddingLength];
|
||||||
|
try {
|
||||||
|
TestUtils.readFully(r.getInputStream(), read1);
|
||||||
|
fail();
|
||||||
|
} catch(FormatException expected) {}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleFrames() throws Exception {
|
public void testMultipleFrames() throws Exception {
|
||||||
// First frame: 123-byte payload
|
// First frame: 123-byte payload
|
||||||
byte[] frame = new byte[6 + 123 + mac.getMacLength()];
|
byte[] frame = new byte[8 + 123 + mac.getMacLength()];
|
||||||
ByteUtils.writeUint16(123, frame, 4); // Frame number 0, length 123
|
writeHeader(frame, 0L, 123, 0);
|
||||||
mac.update(frame, 0, 6 + 123);
|
mac.update(frame, 0, 8 + 123);
|
||||||
mac.doFinal(frame, 6 + 123);
|
mac.doFinal(frame, 8 + 123);
|
||||||
// Second frame: 1234-byte payload
|
// Second frame: 1234-byte payload
|
||||||
byte[] frame1 = new byte[6 + 1234 + mac.getMacLength()];
|
byte[] frame1 = new byte[8 + 1234 + mac.getMacLength()];
|
||||||
ByteUtils.writeUint32(1, frame1, 0); // Frame number 1
|
writeHeader(frame1, 1L, 1234, 0);
|
||||||
ByteUtils.writeUint16(1234, frame1, 4); // Length 1234
|
mac.update(frame1, 0, 8 + 1234);
|
||||||
mac.update(frame1, 0, 6 + 1234);
|
mac.doFinal(frame1, 8 + 1234);
|
||||||
mac.doFinal(frame1, 6 + 1234);
|
|
||||||
// Concatenate the frames
|
// Concatenate the frames
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
out.write(frame);
|
out.write(frame);
|
||||||
@@ -133,12 +167,12 @@ public class ConnectionReaderImplTest extends TestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCorruptPayload() throws Exception {
|
public void testCorruptPayload() throws Exception {
|
||||||
// Six bytes for the header, eight for the payload
|
int payloadLength = 8;
|
||||||
byte[] frame = new byte[6 + 8 + mac.getMacLength()];
|
byte[] frame = new byte[headerLength + payloadLength + macLength];
|
||||||
ByteUtils.writeUint16(8, frame, 4); // Frame number 0, length 8
|
writeHeader(frame, 0L, payloadLength, 0);
|
||||||
// Calculate the MAC
|
// Calculate the MAC
|
||||||
mac.update(frame, 0, 6 + 8);
|
mac.update(frame, 0, headerLength + payloadLength);
|
||||||
mac.doFinal(frame, 6 + 8);
|
mac.doFinal(frame, headerLength + payloadLength);
|
||||||
// Modify the payload
|
// Modify the payload
|
||||||
frame[12] ^= 1;
|
frame[12] ^= 1;
|
||||||
// Try to read the frame - not a single byte should be read
|
// Try to read the frame - not a single byte should be read
|
||||||
@@ -153,12 +187,12 @@ public class ConnectionReaderImplTest extends TestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCorruptMac() throws Exception {
|
public void testCorruptMac() throws Exception {
|
||||||
// Six bytes for the header, eight for the payload
|
int payloadLength = 8;
|
||||||
byte[] frame = new byte[6 + 8 + mac.getMacLength()];
|
byte[] frame = new byte[headerLength + payloadLength + macLength];
|
||||||
ByteUtils.writeUint16(8, frame, 4); // Frame number 0, length 8
|
writeHeader(frame, 0L, payloadLength, 0);
|
||||||
// Calculate the MAC
|
// Calculate the MAC
|
||||||
mac.update(frame, 0, 6 + 8);
|
mac.update(frame, 0, headerLength + payloadLength);
|
||||||
mac.doFinal(frame, 6 + 8);
|
mac.doFinal(frame, headerLength + payloadLength);
|
||||||
// Modify the MAC
|
// Modify the MAC
|
||||||
frame[17] ^= 1;
|
frame[17] ^= 1;
|
||||||
// Try to read the frame - not a single byte should be read
|
// Try to read the frame - not a single byte should be read
|
||||||
@@ -171,6 +205,12 @@ public class ConnectionReaderImplTest extends TestCase {
|
|||||||
} catch(FormatException expected) {}
|
} catch(FormatException expected) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void writeHeader(byte[] b, long frame, int payload, int padding) {
|
||||||
|
ByteUtils.writeUint32(frame, b, 0);
|
||||||
|
ByteUtils.writeUint16(payload, b, 4);
|
||||||
|
ByteUtils.writeUint16(padding, b, 6);
|
||||||
|
}
|
||||||
|
|
||||||
/** A ConnectionDecrypter that performs no decryption. */
|
/** A ConnectionDecrypter that performs no decryption. */
|
||||||
private static class NullConnectionDecrypter
|
private static class NullConnectionDecrypter
|
||||||
implements ConnectionDecrypter {
|
implements ConnectionDecrypter {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import com.google.inject.Injector;
|
|||||||
public class ConnectionWriterImplTest extends TestCase {
|
public class ConnectionWriterImplTest extends TestCase {
|
||||||
|
|
||||||
private final Mac mac;
|
private final Mac mac;
|
||||||
|
private final int headerLength = 8, macLength;
|
||||||
|
|
||||||
public ConnectionWriterImplTest() throws Exception {
|
public ConnectionWriterImplTest() throws Exception {
|
||||||
super();
|
super();
|
||||||
@@ -30,6 +31,7 @@ public class ConnectionWriterImplTest extends TestCase {
|
|||||||
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
||||||
mac = crypto.getMac();
|
mac = crypto.getMac();
|
||||||
mac.init(crypto.generateSecretKey());
|
mac.init(crypto.generateSecretKey());
|
||||||
|
macLength = mac.getMacLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -45,12 +47,12 @@ public class ConnectionWriterImplTest extends TestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleByteFrame() throws Exception {
|
public void testSingleByteFrame() throws Exception {
|
||||||
// Six bytes for the header, one for the payload
|
int payloadLength = 1;
|
||||||
byte[] frame = new byte[6 + 1 + mac.getMacLength()];
|
byte[] frame = new byte[headerLength + payloadLength + macLength];
|
||||||
ByteUtils.writeUint16(1, frame, 4); // Payload length = 1
|
writeHeader(frame, 0L, payloadLength, 0);
|
||||||
// Calculate the MAC
|
// Calculate the MAC
|
||||||
mac.update(frame, 0, 6 + 1);
|
mac.update(frame, 0, headerLength + payloadLength);
|
||||||
mac.doFinal(frame, 6 + 1);
|
mac.doFinal(frame, headerLength + payloadLength);
|
||||||
// Check that the ConnectionWriter gets the same results
|
// Check that the ConnectionWriter gets the same results
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
ConnectionEncrypter e = new NullConnectionEncrypter(out);
|
ConnectionEncrypter e = new NullConnectionEncrypter(out);
|
||||||
@@ -62,7 +64,7 @@ public class ConnectionWriterImplTest extends TestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFrameIsWrittenAtMaxLength() throws Exception {
|
public void testFrameIsWrittenAtMaxLength() throws Exception {
|
||||||
int maxPayloadLength = MAX_FRAME_LENGTH - 6 - mac.getMacLength();
|
int maxPayloadLength = MAX_FRAME_LENGTH - headerLength - macLength;
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
ConnectionEncrypter e = new NullConnectionEncrypter(out);
|
ConnectionEncrypter e = new NullConnectionEncrypter(out);
|
||||||
ConnectionWriter w = new ConnectionWriterImpl(e, mac);
|
ConnectionWriter w = new ConnectionWriterImpl(e, mac);
|
||||||
@@ -75,22 +77,22 @@ public class ConnectionWriterImplTest extends TestCase {
|
|||||||
assertEquals(MAX_FRAME_LENGTH, out.size());
|
assertEquals(MAX_FRAME_LENGTH, out.size());
|
||||||
// Flushing the stream should write a single-byte frame
|
// Flushing the stream should write a single-byte frame
|
||||||
out1.flush();
|
out1.flush();
|
||||||
assertEquals(MAX_FRAME_LENGTH + 6 + 1 + mac.getMacLength(), out.size());
|
assertEquals(MAX_FRAME_LENGTH + headerLength + 1 + macLength,
|
||||||
|
out.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleFrames() throws Exception {
|
public void testMultipleFrames() throws Exception {
|
||||||
// First frame: 123-byte payload
|
// First frame: 123-byte payload
|
||||||
byte[] frame = new byte[6 + 123 + mac.getMacLength()];
|
byte[] frame = new byte[headerLength + 123 + macLength];
|
||||||
ByteUtils.writeUint16(123, frame, 4);
|
writeHeader(frame, 0L, 123, 0);
|
||||||
mac.update(frame, 0, 6 + 123);
|
mac.update(frame, 0, headerLength + 123);
|
||||||
mac.doFinal(frame, 6 + 123);
|
mac.doFinal(frame, headerLength + 123);
|
||||||
// Second frame: 1234-byte payload
|
// Second frame: 1234-byte payload
|
||||||
byte[] frame1 = new byte[6 + 1234 + mac.getMacLength()];
|
byte[] frame1 = new byte[headerLength + 1234 + macLength];
|
||||||
ByteUtils.writeUint32(1, frame1, 0);
|
writeHeader(frame1, 1L, 1234, 0);
|
||||||
ByteUtils.writeUint16(1234, frame1, 4);
|
mac.update(frame1, 0, headerLength + 1234);
|
||||||
mac.update(frame1, 0, 6 + 1234);
|
mac.doFinal(frame1, headerLength + 1234);
|
||||||
mac.doFinal(frame1, 6 + 1234);
|
|
||||||
// Concatenate the frames
|
// Concatenate the frames
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
out.write(frame);
|
out.write(frame);
|
||||||
@@ -108,6 +110,12 @@ public class ConnectionWriterImplTest extends TestCase {
|
|||||||
assertTrue(Arrays.equals(expected, actual));
|
assertTrue(Arrays.equals(expected, actual));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void writeHeader(byte[] b, long frame, int payload, int padding) {
|
||||||
|
ByteUtils.writeUint32(frame, b, 0);
|
||||||
|
ByteUtils.writeUint16(payload, b, 4);
|
||||||
|
ByteUtils.writeUint16(padding, b, 6);
|
||||||
|
}
|
||||||
|
|
||||||
/** A ConnectionEncrypter that performs no encryption. */
|
/** A ConnectionEncrypter that performs no encryption. */
|
||||||
private static class NullConnectionEncrypter
|
private static class NullConnectionEncrypter
|
||||||
implements ConnectionEncrypter {
|
implements ConnectionEncrypter {
|
||||||
|
|||||||
Reference in New Issue
Block a user