PacketWriter is implemented by two classes: PacketWriterImpl and

PacketEncrypter. The separation allows authentication and encryption
to be tested separately.
This commit is contained in:
akwizgran
2011-08-09 17:50:54 +01:00
parent e9d0021f56
commit f3f0c223c4
9 changed files with 274 additions and 13 deletions

View File

@@ -0,0 +1,76 @@
package net.sf.briar.transport;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import junit.framework.TestCase;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.crypto.CryptoModule;
import org.junit.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class PacketEncrypterImplTest extends TestCase {
private final Cipher tagCipher, packetCipher;
private final SecretKey tagKey, packetKey;
public PacketEncrypterImplTest() {
super();
Injector i = Guice.createInjector(new CryptoModule());
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
tagCipher = crypto.getTagCipher();
packetCipher = crypto.getPacketCipher();
tagKey = crypto.generateSecretKey();
packetKey = crypto.generateSecretKey();
}
@Test
public void testSingleBytePacket() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
PacketEncrypter p = new PacketEncrypterImpl(out, tagCipher,
packetCipher, tagKey, packetKey);
p.writeTag(new byte[16]);
p.getOutputStream().write((byte) 0);
p.finishPacket();
assertEquals(17, out.toByteArray().length);
}
@Test
public void testEncryption() throws Exception {
byte[] tag = new byte[16];
byte[] packet = new byte[123];
// Calculate the expected encrypted tag
tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
byte[] expectedTag = tagCipher.doFinal(tag);
assertEquals(tag.length, expectedTag.length);
// Calculate the expected encrypted packet
IvParameterSpec iv = new IvParameterSpec(tag);
packetCipher.init(Cipher.ENCRYPT_MODE, packetKey, iv);
byte[] expectedPacket = packetCipher.doFinal(packet);
assertEquals(packet.length, expectedPacket.length);
// Check that the PacketEncrypter gets the same results
ByteArrayOutputStream out = new ByteArrayOutputStream();
PacketEncrypter p = new PacketEncrypterImpl(out, tagCipher,
packetCipher, tagKey, packetKey);
p.writeTag(tag);
p.getOutputStream().write(packet);
p.finishPacket();
byte[] ciphertext = out.toByteArray();
assertEquals(16 + packet.length, ciphertext.length);
// Check the tag
byte[] actualTag = new byte[16];
System.arraycopy(ciphertext, 0, actualTag, 0, 16);
assertTrue(Arrays.equals(expectedTag, actualTag));
// Check the packet
byte[] actualPacket = new byte[packet.length];
System.arraycopy(ciphertext, 16, actualPacket, 0, actualPacket.length);
assertTrue(Arrays.equals(expectedPacket, actualPacket));
}
}

View File

@@ -1,6 +1,8 @@
package net.sf.briar.transport;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import javax.crypto.Mac;
@@ -31,7 +33,8 @@ public class PacketWriterImplTest extends TestCase {
@Test
public void testFirstWriteTriggersTag() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
PacketWriter p = new PacketWriterImpl(out, mac, 0, 0L);
PacketEncrypter e = new NullPacketEncrypter(out);
PacketWriter p = new PacketWriterImpl(e, mac, 0, 0L);
p.getOutputStream().write(0);
// There should be 16 zero bytes for the tag, 1 for the byte written
assertTrue(Arrays.equals(new byte[17], out.toByteArray()));
@@ -44,7 +47,8 @@ public class PacketWriterImplTest extends TestCase {
byte[] expectedMac = mac.doFinal();
// Check that the PacketWriter calculates and writes the correct MAC
ByteArrayOutputStream out = new ByteArrayOutputStream();
PacketWriter p = new PacketWriterImpl(out, mac, 0, 0L);
PacketEncrypter e = new NullPacketEncrypter(out);
PacketWriter p = new PacketWriterImpl(e, mac, 0, 0L);
p.getOutputStream().write(0);
p.nextPacket();
byte[] written = out.toByteArray();
@@ -61,7 +65,8 @@ public class PacketWriterImplTest extends TestCase {
byte[] expectedMac = mac.doFinal();
// Check that the PacketWriter calculates and writes the correct MAC
ByteArrayOutputStream out = new ByteArrayOutputStream();
PacketWriter p = new PacketWriterImpl(out, mac, 0, 0L);
PacketEncrypter e = new NullPacketEncrypter(out);
PacketWriter p = new PacketWriterImpl(e, mac, 0, 0L);
// Initial calls to nextPacket() should have no effect
p.nextPacket();
p.nextPacket();
@@ -105,7 +110,8 @@ public class PacketWriterImplTest extends TestCase {
byte[] expectedMac1 = mac.doFinal();
// Check that the PacketWriter writes the correct tags and MACs
ByteArrayOutputStream out = new ByteArrayOutputStream();
PacketWriter p = new PacketWriterImpl(out, mac, 0xF00D, 0xDEADBEEFL);
PacketEncrypter e = new NullPacketEncrypter(out);
PacketWriter p = new PacketWriterImpl(e, mac, 0xF00D, 0xDEADBEEFL);
// Packet one
p.getOutputStream().write(0);
p.nextPacket();
@@ -133,4 +139,45 @@ public class PacketWriterImplTest extends TestCase {
actualMac1.length);
assertTrue(Arrays.equals(expectedMac1, actualMac1));
}
@Test
public void testWriteUint16() throws Exception {
byte[] b = new byte[3];
PacketWriterImpl.writeUint16(0, b, 1);
assertEquals("000000", StringUtils.toHexString(b));
PacketWriterImpl.writeUint16(1, b, 1);
assertEquals("000001", StringUtils.toHexString(b));
PacketWriterImpl.writeUint16(65535, b, 1);
assertEquals("00FFFF", StringUtils.toHexString(b));
}
@Test
public void testWriteUint32() throws Exception {
byte[] b = new byte[5];
PacketWriterImpl.writeUint32(0L, b, 1);
assertEquals("0000000000", StringUtils.toHexString(b));
PacketWriterImpl.writeUint32(1L, b, 1);
assertEquals("0000000001", StringUtils.toHexString(b));
PacketWriterImpl.writeUint32(4294967295L, b, 1);
assertEquals("00FFFFFFFF", StringUtils.toHexString(b));
}
private static class NullPacketEncrypter implements PacketEncrypter {
private final OutputStream out;
private NullPacketEncrypter(OutputStream out) {
this.out = out;
}
public OutputStream getOutputStream() {
return out;
}
public void writeTag(byte[] tag) throws IOException {
out.write(tag);
}
public void finishPacket() {}
}
}