mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Converted the outgoing encryption layer from frames to segments.
This commit is contained in:
@@ -50,8 +50,11 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
|
||||
Cipher frameCipher = crypto.getFrameCipher();
|
||||
OutgoingEncryptionLayer encrypter = new OutgoingEncryptionLayerImpl(out,
|
||||
capacity, tagCipher, frameCipher, tagKey, frameKey, false);
|
||||
// No error correction
|
||||
OutgoingErrorCorrectionLayer correcter =
|
||||
new NullOutgoingErrorCorrectionLayer(encrypter);
|
||||
// Create the writer
|
||||
Mac mac = crypto.getMac();
|
||||
return new ConnectionWriterImpl(encrypter, mac, macKey);
|
||||
return new ConnectionWriterImpl(correcter, mac, macKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,16 +23,16 @@ import net.sf.briar.api.transport.ConnectionWriter;
|
||||
*/
|
||||
class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
|
||||
|
||||
private final OutgoingEncryptionLayer encrypter;
|
||||
private final OutgoingErrorCorrectionLayer out;
|
||||
private final Mac mac;
|
||||
private final byte[] buf;
|
||||
private final Frame frame;
|
||||
|
||||
private int length = FRAME_HEADER_LENGTH;
|
||||
private long frame = 0L;
|
||||
private int offset = FRAME_HEADER_LENGTH;
|
||||
private long frameNumber = 0L;
|
||||
|
||||
ConnectionWriterImpl(OutgoingEncryptionLayer encrypter, Mac mac,
|
||||
ConnectionWriterImpl(OutgoingErrorCorrectionLayer out, Mac mac,
|
||||
ErasableKey macKey) {
|
||||
this.encrypter = encrypter;
|
||||
this.out = out;
|
||||
this.mac = mac;
|
||||
// Initialise the MAC
|
||||
try {
|
||||
@@ -43,7 +43,7 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
|
||||
macKey.erase();
|
||||
if(mac.getMacLength() != MAC_LENGTH)
|
||||
throw new IllegalArgumentException();
|
||||
buf = new byte[MAX_FRAME_LENGTH];
|
||||
frame = new Frame();
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
@@ -51,10 +51,10 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
|
||||
}
|
||||
|
||||
public long getRemainingCapacity() {
|
||||
long capacity = encrypter.getRemainingCapacity();
|
||||
long capacity = out.getRemainingCapacity();
|
||||
// If there's any data buffered, subtract it and its overhead
|
||||
if(length > FRAME_HEADER_LENGTH)
|
||||
capacity -= length + MAC_LENGTH;
|
||||
if(offset > FRAME_HEADER_LENGTH)
|
||||
capacity -= offset + MAC_LENGTH;
|
||||
// Subtract the overhead from the remaining capacity
|
||||
long frames = (long) Math.ceil((double) capacity / MAX_FRAME_LENGTH);
|
||||
int overheadPerFrame = FRAME_HEADER_LENGTH + MAC_LENGTH;
|
||||
@@ -63,14 +63,14 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
if(length > FRAME_HEADER_LENGTH) writeFrame();
|
||||
encrypter.flush();
|
||||
if(offset > FRAME_HEADER_LENGTH) writeFrame();
|
||||
out.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
buf[length++] = (byte) b;
|
||||
if(length + MAC_LENGTH == MAX_FRAME_LENGTH) writeFrame();
|
||||
frame.getBuffer()[offset++] = (byte) b;
|
||||
if(offset + MAC_LENGTH == MAX_FRAME_LENGTH) writeFrame();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -80,32 +80,35 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
int available = MAX_FRAME_LENGTH - length - MAC_LENGTH;
|
||||
byte[] buf = frame.getBuffer();
|
||||
int available = MAX_FRAME_LENGTH - offset - MAC_LENGTH;
|
||||
while(available <= len) {
|
||||
System.arraycopy(b, off, buf, length, available);
|
||||
length += available;
|
||||
System.arraycopy(b, off, buf, offset, available);
|
||||
offset += available;
|
||||
writeFrame();
|
||||
off += available;
|
||||
len -= available;
|
||||
available = MAX_FRAME_LENGTH - length - MAC_LENGTH;
|
||||
available = MAX_FRAME_LENGTH - offset - MAC_LENGTH;
|
||||
}
|
||||
System.arraycopy(b, off, buf, length, len);
|
||||
length += len;
|
||||
System.arraycopy(b, off, buf, offset, len);
|
||||
offset += len;
|
||||
}
|
||||
|
||||
private void writeFrame() throws IOException {
|
||||
if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException();
|
||||
int payloadLength = length - FRAME_HEADER_LENGTH;
|
||||
if(frameNumber > MAX_32_BIT_UNSIGNED) throw new IllegalStateException();
|
||||
byte[] buf = frame.getBuffer();
|
||||
int payloadLength = offset - FRAME_HEADER_LENGTH;
|
||||
assert payloadLength > 0;
|
||||
HeaderEncoder.encodeHeader(buf, frame, payloadLength, 0);
|
||||
mac.update(buf, 0, length);
|
||||
HeaderEncoder.encodeHeader(buf, frameNumber, payloadLength, 0);
|
||||
mac.update(buf, 0, offset);
|
||||
try {
|
||||
mac.doFinal(buf, length);
|
||||
mac.doFinal(buf, offset);
|
||||
} catch(ShortBufferException badMac) {
|
||||
throw new RuntimeException(badMac);
|
||||
}
|
||||
encrypter.writeFrame(buf, length + MAC_LENGTH);
|
||||
length = FRAME_HEADER_LENGTH;
|
||||
frame++;
|
||||
frame.setLength(offset + MAC_LENGTH);
|
||||
out.writeFrame(frame);
|
||||
offset = FRAME_HEADER_LENGTH;
|
||||
frameNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class IncomingEncryptionLayerImpl implements IncomingEncryptionLayer {
|
||||
blockSize = frameCipher.getBlockSize();
|
||||
if(blockSize < FRAME_HEADER_LENGTH)
|
||||
throw new IllegalArgumentException();
|
||||
iv = IvEncoder.encodeIv(0, blockSize);
|
||||
iv = IvEncoder.encodeIv(0L, blockSize);
|
||||
ciphertext = new byte[MAX_SEGMENT_LENGTH];
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class IncomingSegmentedEncryptionLayer implements IncomingEncryptionLayer {
|
||||
blockSize = frameCipher.getBlockSize();
|
||||
if(blockSize < FRAME_HEADER_LENGTH)
|
||||
throw new IllegalArgumentException();
|
||||
iv = IvEncoder.encodeIv(0, blockSize);
|
||||
iv = IvEncoder.encodeIv(0L, blockSize);
|
||||
segment = new SegmentImpl();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.sf.briar.api.plugins.Segment;
|
||||
|
||||
class NullOutgoingErrorCorrectionLayer implements OutgoingErrorCorrectionLayer {
|
||||
|
||||
private final OutgoingEncryptionLayer out;
|
||||
private final Segment segment;
|
||||
|
||||
private long segmentNumber = 0L;
|
||||
|
||||
public NullOutgoingErrorCorrectionLayer(OutgoingEncryptionLayer out) {
|
||||
this.out = out;
|
||||
segment = new SegmentImpl();
|
||||
}
|
||||
|
||||
public void writeFrame(Frame f) throws IOException {
|
||||
if(segmentNumber > MAX_32_BIT_UNSIGNED)
|
||||
throw new IllegalStateException();
|
||||
int length = f.getLength();
|
||||
// FIXME: Unnecessary copy
|
||||
System.arraycopy(f.getBuffer(), 0, segment.getBuffer(), 0, length);
|
||||
segment.setLength(length);
|
||||
segment.setSegmentNumber(segmentNumber++);
|
||||
out.writeSegment(segment);
|
||||
}
|
||||
|
||||
public void flush() throws IOException {
|
||||
out.flush();
|
||||
}
|
||||
|
||||
public long getRemainingCapacity() {
|
||||
return out.getRemainingCapacity();
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,14 @@ package net.sf.briar.transport;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/** Encrypts authenticated data to be sent over a connection. */
|
||||
import net.sf.briar.api.plugins.Segment;
|
||||
|
||||
interface OutgoingEncryptionLayer {
|
||||
|
||||
/** Writes the given frame. */
|
||||
void writeFrame(byte[] b, int len) throws IOException;
|
||||
/** Writes the given segment. */
|
||||
void writeSegment(Segment s) throws IOException;
|
||||
|
||||
/** Flushes the output stream. */
|
||||
/** Flushes the stack. */
|
||||
void flush() throws IOException;
|
||||
|
||||
/** Returns the maximum number of bytes that can be written. */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@@ -11,6 +11,7 @@ import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.api.plugins.Segment;
|
||||
|
||||
class OutgoingEncryptionLayerImpl implements OutgoingEncryptionLayer {
|
||||
|
||||
@@ -18,13 +19,13 @@ class OutgoingEncryptionLayerImpl implements OutgoingEncryptionLayer {
|
||||
private final Cipher tagCipher, frameCipher;
|
||||
private final ErasableKey tagKey, frameKey;
|
||||
private final boolean tagEverySegment;
|
||||
private final byte[] iv, tag;
|
||||
private final byte[] iv, ciphertext;
|
||||
|
||||
private long capacity, frame = 0L;
|
||||
private long capacity;
|
||||
|
||||
OutgoingEncryptionLayerImpl(OutputStream out, long capacity, Cipher tagCipher,
|
||||
Cipher frameCipher, ErasableKey tagKey, ErasableKey frameKey,
|
||||
boolean tagEverySegment) {
|
||||
OutgoingEncryptionLayerImpl(OutputStream out, long capacity,
|
||||
Cipher tagCipher, Cipher frameCipher, ErasableKey tagKey,
|
||||
ErasableKey frameKey, boolean tagEverySegment) {
|
||||
this.out = out;
|
||||
this.capacity = capacity;
|
||||
this.tagCipher = tagCipher;
|
||||
@@ -32,35 +33,37 @@ class OutgoingEncryptionLayerImpl implements OutgoingEncryptionLayer {
|
||||
this.tagKey = tagKey;
|
||||
this.frameKey = frameKey;
|
||||
this.tagEverySegment = tagEverySegment;
|
||||
iv = IvEncoder.encodeIv(0, frameCipher.getBlockSize());
|
||||
tag = new byte[TAG_LENGTH];
|
||||
iv = IvEncoder.encodeIv(0L, frameCipher.getBlockSize());
|
||||
ciphertext = new byte[MAX_SEGMENT_LENGTH];
|
||||
}
|
||||
|
||||
public void writeFrame(byte[] b, int len) throws IOException {
|
||||
if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException();
|
||||
public void writeSegment(Segment s) throws IOException {
|
||||
byte[] plaintext = s.getBuffer();
|
||||
int length = s.getLength();
|
||||
long segmentNumber = s.getSegmentNumber();
|
||||
int offset = 0;
|
||||
if(tagEverySegment || segmentNumber == 0) {
|
||||
TagEncoder.encodeTag(ciphertext, segmentNumber, tagCipher, tagKey);
|
||||
offset = TAG_LENGTH;
|
||||
}
|
||||
IvEncoder.updateIv(iv, segmentNumber);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
try {
|
||||
if(tagEverySegment || frame == 0) {
|
||||
TagEncoder.encodeTag(tag, frame, tagCipher, tagKey);
|
||||
out.write(tag);
|
||||
capacity -= tag.length;
|
||||
}
|
||||
IvEncoder.updateIv(iv, frame);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
try {
|
||||
frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec);
|
||||
int encrypted = frameCipher.doFinal(b, 0, len, b);
|
||||
if(encrypted != len) throw new RuntimeException();
|
||||
} catch(GeneralSecurityException badCipher) {
|
||||
throw new RuntimeException(badCipher);
|
||||
}
|
||||
out.write(b, 0, len);
|
||||
capacity -= len;
|
||||
frame++;
|
||||
frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec);
|
||||
int encrypted = frameCipher.doFinal(plaintext, 0, length,
|
||||
ciphertext, offset);
|
||||
if(encrypted != length) throw new RuntimeException();
|
||||
} catch(GeneralSecurityException badCipher) {
|
||||
throw new RuntimeException(badCipher);
|
||||
}
|
||||
try {
|
||||
out.write(ciphertext, 0, offset + length);
|
||||
} catch(IOException e) {
|
||||
frameKey.erase();
|
||||
tagKey.erase();
|
||||
throw e;
|
||||
}
|
||||
capacity -= offset + length;
|
||||
}
|
||||
|
||||
public void flush() throws IOException {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
interface OutgoingErrorCorrectionLayer {
|
||||
|
||||
/** Writes the given frame. */
|
||||
void writeFrame(Frame f) throws IOException;
|
||||
|
||||
/** Flushes the stack. */
|
||||
void flush() throws IOException;
|
||||
|
||||
/** Returns the maximum number of bytes that can be written. */
|
||||
long getRemainingCapacity();
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
@@ -22,7 +21,7 @@ class OutgoingSegmentedEncryptionLayer implements OutgoingEncryptionLayer {
|
||||
private final byte[] iv;
|
||||
private final Segment segment;
|
||||
|
||||
private long capacity, frame = 0L;
|
||||
private long capacity;
|
||||
|
||||
OutgoingSegmentedEncryptionLayer(SegmentSink out, long capacity,
|
||||
Cipher tagCipher, Cipher frameCipher, ErasableKey tagKey,
|
||||
@@ -34,29 +33,30 @@ class OutgoingSegmentedEncryptionLayer implements OutgoingEncryptionLayer {
|
||||
this.tagKey = tagKey;
|
||||
this.frameKey = frameKey;
|
||||
this.tagEverySegment = tagEverySegment;
|
||||
iv = IvEncoder.encodeIv(0, frameCipher.getBlockSize());
|
||||
iv = IvEncoder.encodeIv(0L, frameCipher.getBlockSize());
|
||||
segment = new SegmentImpl();
|
||||
}
|
||||
|
||||
public void writeFrame(byte[] b, int len) throws IOException {
|
||||
if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException();
|
||||
public void writeSegment(Segment s) throws IOException {
|
||||
byte[] plaintext = s.getBuffer(), ciphertext = segment.getBuffer();
|
||||
int length = s.getLength();
|
||||
long segmentNumber = s.getSegmentNumber();
|
||||
int offset = 0;
|
||||
if(tagEverySegment || frame == 0) {
|
||||
TagEncoder.encodeTag(segment.getBuffer(), frame, tagCipher, tagKey);
|
||||
if(tagEverySegment || segmentNumber == 0) {
|
||||
TagEncoder.encodeTag(ciphertext, segmentNumber, tagCipher, tagKey);
|
||||
offset = TAG_LENGTH;
|
||||
capacity -= TAG_LENGTH;
|
||||
}
|
||||
IvEncoder.updateIv(iv, frame);
|
||||
IvEncoder.updateIv(iv, segmentNumber);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
try {
|
||||
frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec);
|
||||
int encrypted = frameCipher.doFinal(b, 0, len, segment.getBuffer(),
|
||||
offset);
|
||||
if(encrypted != len) throw new RuntimeException();
|
||||
int encrypted = frameCipher.doFinal(plaintext, 0, length,
|
||||
ciphertext, offset);
|
||||
if(encrypted != length) throw new RuntimeException();
|
||||
} catch(GeneralSecurityException badCipher) {
|
||||
throw new RuntimeException(badCipher);
|
||||
}
|
||||
segment.setLength(offset + len);
|
||||
segment.setLength(offset + length);
|
||||
try {
|
||||
out.writeSegment(segment);
|
||||
} catch(IOException e) {
|
||||
@@ -64,8 +64,7 @@ class OutgoingSegmentedEncryptionLayer implements OutgoingEncryptionLayer {
|
||||
tagKey.erase();
|
||||
throw e;
|
||||
}
|
||||
capacity -= len;
|
||||
frame++;
|
||||
capacity -= offset + length;
|
||||
}
|
||||
|
||||
public void flush() throws IOException {}
|
||||
|
||||
@@ -17,6 +17,8 @@ class TagEncoder {
|
||||
if(tag.length < TAG_LENGTH) throw new IllegalArgumentException();
|
||||
if(segmentNumber < 0 || segmentNumber > MAX_32_BIT_UNSIGNED)
|
||||
throw new IllegalArgumentException();
|
||||
// Clear the tag
|
||||
for(int i = 0; i < TAG_LENGTH; i++) tag[i] = 0;
|
||||
// Encode the segment number as a uint32 at the end of the tag
|
||||
ByteUtils.writeUint32(segmentNumber, tag, TAG_LENGTH - 4);
|
||||
try {
|
||||
|
||||
@@ -21,8 +21,11 @@ public class ConnectionWriterImplTest extends TransportTest {
|
||||
@Test
|
||||
public void testFlushWithoutWriteProducesNothing() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
OutgoingEncryptionLayer encrypter = new NullOutgoingEncryptionLayer(out);
|
||||
ConnectionWriter w = new ConnectionWriterImpl(encrypter, mac, macKey);
|
||||
OutgoingEncryptionLayer encrypter =
|
||||
new NullOutgoingEncryptionLayer(out);
|
||||
OutgoingErrorCorrectionLayer correcter =
|
||||
new NullOutgoingErrorCorrectionLayer(encrypter);
|
||||
ConnectionWriter w = new ConnectionWriterImpl(correcter, mac, macKey);
|
||||
w.getOutputStream().flush();
|
||||
w.getOutputStream().flush();
|
||||
w.getOutputStream().flush();
|
||||
@@ -41,8 +44,11 @@ public class ConnectionWriterImplTest extends TransportTest {
|
||||
mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength);
|
||||
// Check that the ConnectionWriter gets the same results
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
OutgoingEncryptionLayer encrypter = new NullOutgoingEncryptionLayer(out);
|
||||
ConnectionWriter w = new ConnectionWriterImpl(encrypter, mac, macKey);
|
||||
OutgoingEncryptionLayer encrypter =
|
||||
new NullOutgoingEncryptionLayer(out);
|
||||
OutgoingErrorCorrectionLayer correcter =
|
||||
new NullOutgoingErrorCorrectionLayer(encrypter);
|
||||
ConnectionWriter w = new ConnectionWriterImpl(correcter, mac, macKey);
|
||||
w.getOutputStream().write(0);
|
||||
w.getOutputStream().flush();
|
||||
assertArrayEquals(frame, out.toByteArray());
|
||||
@@ -51,8 +57,11 @@ public class ConnectionWriterImplTest extends TransportTest {
|
||||
@Test
|
||||
public void testWriteByteToMaxLengthWritesFrame() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
OutgoingEncryptionLayer encrypter = new NullOutgoingEncryptionLayer(out);
|
||||
ConnectionWriter w = new ConnectionWriterImpl(encrypter, mac, macKey);
|
||||
OutgoingEncryptionLayer encrypter =
|
||||
new NullOutgoingEncryptionLayer(out);
|
||||
OutgoingErrorCorrectionLayer correcter =
|
||||
new NullOutgoingErrorCorrectionLayer(encrypter);
|
||||
ConnectionWriter w = new ConnectionWriterImpl(correcter, mac, macKey);
|
||||
OutputStream out1 = w.getOutputStream();
|
||||
// The first maxPayloadLength - 1 bytes should be buffered
|
||||
for(int i = 0; i < MAX_PAYLOAD_LENGTH - 1; i++) out1.write(0);
|
||||
@@ -65,8 +74,11 @@ public class ConnectionWriterImplTest extends TransportTest {
|
||||
@Test
|
||||
public void testWriteArrayToMaxLengthWritesFrame() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
OutgoingEncryptionLayer encrypter = new NullOutgoingEncryptionLayer(out);
|
||||
ConnectionWriter w = new ConnectionWriterImpl(encrypter, mac, macKey);
|
||||
OutgoingEncryptionLayer encrypter =
|
||||
new NullOutgoingEncryptionLayer(out);
|
||||
OutgoingErrorCorrectionLayer correcter =
|
||||
new NullOutgoingErrorCorrectionLayer(encrypter);
|
||||
ConnectionWriter w = new ConnectionWriterImpl(correcter, mac, macKey);
|
||||
OutputStream out1 = w.getOutputStream();
|
||||
// The first maxPayloadLength - 1 bytes should be buffered
|
||||
out1.write(new byte[MAX_PAYLOAD_LENGTH - 1]);
|
||||
@@ -100,8 +112,11 @@ public class ConnectionWriterImplTest extends TransportTest {
|
||||
byte[] expected = out.toByteArray();
|
||||
// Check that the ConnectionWriter gets the same results
|
||||
out.reset();
|
||||
OutgoingEncryptionLayer encrypter = new NullOutgoingEncryptionLayer(out);
|
||||
ConnectionWriter w = new ConnectionWriterImpl(encrypter, mac, macKey);
|
||||
OutgoingEncryptionLayer encrypter =
|
||||
new NullOutgoingEncryptionLayer(out);
|
||||
OutgoingErrorCorrectionLayer correcter =
|
||||
new NullOutgoingErrorCorrectionLayer(encrypter);
|
||||
ConnectionWriter w = new ConnectionWriterImpl(correcter, mac, macKey);
|
||||
w.getOutputStream().write(new byte[123]);
|
||||
w.getOutputStream().flush();
|
||||
w.getOutputStream().write(new byte[1234]);
|
||||
|
||||
@@ -77,7 +77,9 @@ public class FrameReadWriteTest extends BriarTestCase {
|
||||
OutgoingEncryptionLayer encrypter = new OutgoingEncryptionLayerImpl(out,
|
||||
Long.MAX_VALUE, tagCipher, frameCipher, tagCopy, frameCopy,
|
||||
false);
|
||||
ConnectionWriter writer = new ConnectionWriterImpl(encrypter, mac,
|
||||
OutgoingErrorCorrectionLayer correcter =
|
||||
new NullOutgoingErrorCorrectionLayer(encrypter);
|
||||
ConnectionWriter writer = new ConnectionWriterImpl(correcter, mac,
|
||||
macCopy);
|
||||
OutputStream out1 = writer.getOutputStream();
|
||||
out1.write(frame);
|
||||
@@ -93,9 +95,9 @@ public class FrameReadWriteTest extends BriarTestCase {
|
||||
// Read the frames back
|
||||
IncomingEncryptionLayer decrypter = new IncomingEncryptionLayerImpl(in,
|
||||
tagCipher, frameCipher, tagKey, frameKey, false);
|
||||
IncomingErrorCorrectionLayer correcter =
|
||||
IncomingErrorCorrectionLayer correcter1 =
|
||||
new NullIncomingErrorCorrectionLayer(decrypter);
|
||||
ConnectionReader reader = new ConnectionReaderImpl(correcter, mac,
|
||||
ConnectionReader reader = new ConnectionReaderImpl(correcter1, mac,
|
||||
macKey);
|
||||
InputStream in1 = reader.getInputStream();
|
||||
byte[] recovered = new byte[frame.length];
|
||||
|
||||
@@ -3,6 +3,8 @@ package net.sf.briar.transport;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import net.sf.briar.api.plugins.Segment;
|
||||
|
||||
/** An encryption layer that performs no encryption. */
|
||||
class NullOutgoingEncryptionLayer implements OutgoingEncryptionLayer {
|
||||
|
||||
@@ -20,9 +22,9 @@ class NullOutgoingEncryptionLayer implements OutgoingEncryptionLayer {
|
||||
this.capacity = capacity;
|
||||
}
|
||||
|
||||
public void writeFrame(byte[] b, int len) throws IOException {
|
||||
out.write(b, 0, len);
|
||||
capacity -= len;
|
||||
public void writeSegment(Segment s) throws IOException {
|
||||
out.write(s.getBuffer(), 0, s.getLength());
|
||||
capacity -= s.getLength();
|
||||
}
|
||||
|
||||
public void flush() throws IOException {
|
||||
|
||||
@@ -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.plugins.Segment;
|
||||
import net.sf.briar.crypto.CryptoModule;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -63,8 +64,15 @@ public class OutgoingEncryptionLayerImplTest extends BriarTestCase {
|
||||
OutgoingEncryptionLayer encrypter = new OutgoingEncryptionLayerImpl(out,
|
||||
Long.MAX_VALUE, tagCipher, frameCipher, tagKey, frameKey,
|
||||
false);
|
||||
encrypter.writeFrame(plaintext, plaintext.length);
|
||||
encrypter.writeFrame(plaintext1, plaintext1.length);
|
||||
Segment s = new SegmentImpl();
|
||||
System.arraycopy(plaintext, 0, s.getBuffer(), 0, plaintext.length);
|
||||
s.setLength(plaintext.length);
|
||||
s.setSegmentNumber(0L);
|
||||
encrypter.writeSegment(s);
|
||||
System.arraycopy(plaintext1, 0, s.getBuffer(), 0, plaintext1.length);
|
||||
s.setLength(plaintext1.length);
|
||||
s.setSegmentNumber(1L);
|
||||
encrypter.writeSegment(s);
|
||||
byte[] actual = out.toByteArray();
|
||||
// Check that the actual ciphertext matches the expected ciphertext
|
||||
assertArrayEquals(expected, actual);
|
||||
@@ -103,8 +111,15 @@ public class OutgoingEncryptionLayerImplTest extends BriarTestCase {
|
||||
out.reset();
|
||||
OutgoingEncryptionLayer encrypter = new OutgoingEncryptionLayerImpl(out,
|
||||
Long.MAX_VALUE, tagCipher, frameCipher, tagKey, frameKey, true);
|
||||
encrypter.writeFrame(plaintext, plaintext.length);
|
||||
encrypter.writeFrame(plaintext1, plaintext1.length);
|
||||
Segment s = new SegmentImpl();
|
||||
System.arraycopy(plaintext, 0, s.getBuffer(), 0, plaintext.length);
|
||||
s.setLength(plaintext.length);
|
||||
s.setSegmentNumber(0L);
|
||||
encrypter.writeSegment(s);
|
||||
System.arraycopy(plaintext1, 0, s.getBuffer(), 0, plaintext1.length);
|
||||
s.setLength(plaintext1.length);
|
||||
s.setSegmentNumber(1L);
|
||||
encrypter.writeSegment(s);
|
||||
byte[] actual = out.toByteArray();
|
||||
// Check that the actual ciphertext matches the expected ciphertext
|
||||
assertArrayEquals(expected, actual);
|
||||
|
||||
@@ -66,9 +66,15 @@ public class OutgoingSegmentedEncryptionLayerTest extends BriarTestCase {
|
||||
OutgoingEncryptionLayer encrypter =
|
||||
new OutgoingSegmentedEncryptionLayer(sink, Long.MAX_VALUE,
|
||||
tagCipher, frameCipher, tagKey, frameKey, false);
|
||||
// The first frame's buffer must have enough space for the tag
|
||||
encrypter.writeFrame(plaintext, plaintext.length);
|
||||
encrypter.writeFrame(plaintext1, plaintext1.length);
|
||||
Segment s = new SegmentImpl();
|
||||
System.arraycopy(plaintext, 0, s.getBuffer(), 0, plaintext.length);
|
||||
s.setLength(plaintext.length);
|
||||
s.setSegmentNumber(0L);
|
||||
encrypter.writeSegment(s);
|
||||
System.arraycopy(plaintext1, 0, s.getBuffer(), 0, plaintext1.length);
|
||||
s.setLength(plaintext1.length);
|
||||
s.setSegmentNumber(1L);
|
||||
encrypter.writeSegment(s);
|
||||
byte[] actual = out.toByteArray();
|
||||
// Check that the actual ciphertext matches the expected ciphertext
|
||||
assertArrayEquals(expected, actual);
|
||||
@@ -108,8 +114,15 @@ public class OutgoingSegmentedEncryptionLayerTest extends BriarTestCase {
|
||||
OutgoingEncryptionLayer encrypter =
|
||||
new OutgoingSegmentedEncryptionLayer(sink, Long.MAX_VALUE,
|
||||
tagCipher, frameCipher, tagKey, frameKey, true);
|
||||
encrypter.writeFrame(plaintext, plaintext.length);
|
||||
encrypter.writeFrame(plaintext1, plaintext1.length);
|
||||
Segment s = new SegmentImpl();
|
||||
System.arraycopy(plaintext, 0, s.getBuffer(), 0, plaintext.length);
|
||||
s.setLength(plaintext.length);
|
||||
s.setSegmentNumber(0L);
|
||||
encrypter.writeSegment(s);
|
||||
System.arraycopy(plaintext1, 0, s.getBuffer(), 0, plaintext1.length);
|
||||
s.setLength(plaintext1.length);
|
||||
s.setSegmentNumber(1L);
|
||||
encrypter.writeSegment(s);
|
||||
byte[] actual = out.toByteArray();
|
||||
// Check that the actual ciphertext matches the expected ciphertext
|
||||
assertArrayEquals(expected, actual);
|
||||
|
||||
Reference in New Issue
Block a user