mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 13:19:52 +01:00
Use a constant for the tag size.
This commit is contained in:
@@ -10,8 +10,8 @@ import net.sf.briar.api.protocol.SubscriptionUpdate;
|
|||||||
import net.sf.briar.api.protocol.TransportUpdate;
|
import net.sf.briar.api.protocol.TransportUpdate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads unencrypted packets from an underlying input stream and authenticates
|
* Reads encrypted packets from an underlying input stream, decrypts and
|
||||||
* them.
|
* authenticates them.
|
||||||
*/
|
*/
|
||||||
public interface PacketReader {
|
public interface PacketReader {
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import javax.crypto.spec.IvParameterSpec;
|
|||||||
*/
|
*/
|
||||||
class SharedSecret {
|
class SharedSecret {
|
||||||
|
|
||||||
private static final int IV_BYTES = 16;
|
static final int IV_BYTES = 16;
|
||||||
|
|
||||||
private final IvParameterSpec iv;
|
private final IvParameterSpec iv;
|
||||||
private final boolean alice;
|
private final boolean alice;
|
||||||
|
|||||||
@@ -92,7 +92,8 @@ DatabaseListener {
|
|||||||
|
|
||||||
public synchronized ContactId acceptConnection(byte[] tag)
|
public synchronized ContactId acceptConnection(byte[] tag)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
if(tag.length != 16) throw new IllegalArgumentException();
|
if(tag.length != Constants.TAG_BYTES)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
if(!initialised) initialise();
|
if(!initialised) initialise();
|
||||||
Bytes b = new Bytes(tag);
|
Bytes b = new Bytes(tag);
|
||||||
ContactId contactId = tagToContact.remove(b);
|
ContactId contactId = tagToContact.remove(b);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package net.sf.briar.transport;
|
|||||||
|
|
||||||
interface Constants {
|
interface Constants {
|
||||||
|
|
||||||
|
static final int TAG_BYTES = 16;
|
||||||
static final int MAX_16_BIT_UNSIGNED = 65535; // 2^16 - 1
|
static final int MAX_16_BIT_UNSIGNED = 65535; // 2^16 - 1
|
||||||
static final long MAX_32_BIT_UNSIGNED = 4294967295L; // 2^32 - 1
|
static final long MAX_32_BIT_UNSIGNED = 4294967295L; // 2^32 - 1
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,12 @@ import java.io.OutputStream;
|
|||||||
|
|
||||||
interface PacketEncrypter {
|
interface PacketEncrypter {
|
||||||
|
|
||||||
|
/** Returns the output stream to which packets should be written. */
|
||||||
OutputStream getOutputStream();
|
OutputStream getOutputStream();
|
||||||
|
|
||||||
|
/** Encrypts the given tag and writes it to the underlying output stream. */
|
||||||
void writeTag(byte[] tag) throws IOException;
|
void writeTag(byte[] tag) throws IOException;
|
||||||
|
|
||||||
|
/** Finishes writing the current packet. */
|
||||||
void finishPacket() throws IOException;
|
void finishPacket() throws IOException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,14 +15,12 @@ import javax.crypto.spec.IvParameterSpec;
|
|||||||
class PacketEncrypterImpl extends FilterOutputStream
|
class PacketEncrypterImpl extends FilterOutputStream
|
||||||
implements PacketEncrypter {
|
implements PacketEncrypter {
|
||||||
|
|
||||||
private final OutputStream out;
|
|
||||||
private final Cipher tagCipher, packetCipher;
|
private final Cipher tagCipher, packetCipher;
|
||||||
private final SecretKey packetKey;
|
private final SecretKey packetKey;
|
||||||
|
|
||||||
PacketEncrypterImpl(OutputStream out, Cipher tagCipher,
|
PacketEncrypterImpl(OutputStream out, Cipher tagCipher,
|
||||||
Cipher packetCipher, SecretKey tagKey, SecretKey packetKey) {
|
Cipher packetCipher, SecretKey tagKey, SecretKey packetKey) {
|
||||||
super(out);
|
super(out);
|
||||||
this.out = out;
|
|
||||||
this.tagCipher = tagCipher;
|
this.tagCipher = tagCipher;
|
||||||
this.packetCipher = packetCipher;
|
this.packetCipher = packetCipher;
|
||||||
this.packetKey = packetKey;
|
this.packetKey = packetKey;
|
||||||
@@ -31,7 +29,7 @@ implements PacketEncrypter {
|
|||||||
} catch(InvalidKeyException e) {
|
} catch(InvalidKeyException e) {
|
||||||
throw new IllegalArgumentException(e);
|
throw new IllegalArgumentException(e);
|
||||||
}
|
}
|
||||||
if(tagCipher.getOutputSize(16) != 16)
|
if(tagCipher.getOutputSize(Constants.TAG_BYTES) != Constants.TAG_BYTES)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +38,8 @@ implements PacketEncrypter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void writeTag(byte[] tag) throws IOException {
|
public void writeTag(byte[] tag) throws IOException {
|
||||||
if(tag.length != 16) throw new IllegalArgumentException();
|
if(tag.length != Constants.TAG_BYTES)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
IvParameterSpec iv = new IvParameterSpec(tag);
|
IvParameterSpec iv = new IvParameterSpec(tag);
|
||||||
try {
|
try {
|
||||||
out.write(tagCipher.doFinal(tag));
|
out.write(tagCipher.doFinal(tag));
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ public class TagEncoder {
|
|||||||
|
|
||||||
static byte[] encodeTag(int transportIdentifier, long connectionNumber,
|
static byte[] encodeTag(int transportIdentifier, long connectionNumber,
|
||||||
long packetNumber) {
|
long packetNumber) {
|
||||||
byte[] tag = new byte[16];
|
byte[] tag = new byte[Constants.TAG_BYTES];
|
||||||
// Encode the transport identifier as an unsigned 16-bit integer
|
// Encode the transport identifier as an unsigned 16-bit integer
|
||||||
writeUint16(transportIdentifier, tag, 2);
|
writeUint16(transportIdentifier, tag, 2);
|
||||||
// Encode the connection number as an unsigned 32-bit integer
|
// Encode the connection number as an unsigned 32-bit integer
|
||||||
|
|||||||
@@ -14,22 +14,22 @@ public class SharedSecretTest extends TestCase {
|
|||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
byte[] secret = new byte[40];
|
byte[] secret = new byte[40];
|
||||||
random.nextBytes(secret);
|
random.nextBytes(secret);
|
||||||
secret[16] = (byte) 0;
|
secret[SharedSecret.IV_BYTES] = (byte) 0;
|
||||||
SharedSecret s = new SharedSecret(secret);
|
SharedSecret s = new SharedSecret(secret);
|
||||||
assertTrue(Arrays.equals(secret, s.getBytes()));
|
assertTrue(Arrays.equals(secret, s.getBytes()));
|
||||||
secret[16] = (byte) 1;
|
secret[SharedSecret.IV_BYTES] = (byte) 1;
|
||||||
s = new SharedSecret(secret);
|
s = new SharedSecret(secret);
|
||||||
assertTrue(Arrays.equals(secret, s.getBytes()));
|
assertTrue(Arrays.equals(secret, s.getBytes()));
|
||||||
// The Alice flag must be either 0 or 1
|
// The Alice flag must be either 0 or 1
|
||||||
secret[16] = (byte) 2;
|
secret[SharedSecret.IV_BYTES] = (byte) 2;
|
||||||
try {
|
try {
|
||||||
s = new SharedSecret(secret);
|
s = new SharedSecret(secret);
|
||||||
fail();
|
fail();
|
||||||
} catch(IllegalArgumentException expected) {}
|
} catch(IllegalArgumentException expected) {}
|
||||||
// The secret must be at least 18 bytes long
|
// The ciphertext must be at least 1 byte long
|
||||||
secret = new byte[17];
|
secret = new byte[SharedSecret.IV_BYTES + 1];
|
||||||
random.nextBytes(secret);
|
random.nextBytes(secret);
|
||||||
secret[16] = (byte) 0;
|
secret[SharedSecret.IV_BYTES] = (byte) 0;
|
||||||
try {
|
try {
|
||||||
s = new SharedSecret(secret);
|
s = new SharedSecret(secret);
|
||||||
fail();
|
fail();
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public class ConnectionRecogniserImplTest extends TestCase {
|
|||||||
}});
|
}});
|
||||||
final ConnectionRecogniserImpl c =
|
final ConnectionRecogniserImpl c =
|
||||||
new ConnectionRecogniserImpl(transportId, crypto, db);
|
new ConnectionRecogniserImpl(transportId, crypto, db);
|
||||||
assertNull(c.acceptConnection(new byte[16]));
|
assertNull(c.acceptConnection(new byte[Constants.TAG_BYTES]));
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class PacketEncrypterImplTest extends TestCase {
|
|||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
PacketEncrypter p = new PacketEncrypterImpl(out, tagCipher,
|
PacketEncrypter p = new PacketEncrypterImpl(out, tagCipher,
|
||||||
packetCipher, tagKey, packetKey);
|
packetCipher, tagKey, packetKey);
|
||||||
p.writeTag(new byte[16]);
|
p.writeTag(new byte[Constants.TAG_BYTES]);
|
||||||
p.getOutputStream().write((byte) 0);
|
p.getOutputStream().write((byte) 0);
|
||||||
p.finishPacket();
|
p.finishPacket();
|
||||||
assertEquals(17, out.toByteArray().length);
|
assertEquals(17, out.toByteArray().length);
|
||||||
@@ -44,7 +44,7 @@ public class PacketEncrypterImplTest extends TestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncryption() throws Exception {
|
public void testEncryption() throws Exception {
|
||||||
byte[] tag = new byte[16];
|
byte[] tag = new byte[Constants.TAG_BYTES];
|
||||||
byte[] packet = new byte[123];
|
byte[] packet = new byte[123];
|
||||||
// Calculate the expected encrypted tag
|
// Calculate the expected encrypted tag
|
||||||
tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
|
tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
|
||||||
@@ -63,14 +63,15 @@ public class PacketEncrypterImplTest extends TestCase {
|
|||||||
p.getOutputStream().write(packet);
|
p.getOutputStream().write(packet);
|
||||||
p.finishPacket();
|
p.finishPacket();
|
||||||
byte[] ciphertext = out.toByteArray();
|
byte[] ciphertext = out.toByteArray();
|
||||||
assertEquals(16 + packet.length, ciphertext.length);
|
assertEquals(Constants.TAG_BYTES + packet.length, ciphertext.length);
|
||||||
// Check the tag
|
// Check the tag
|
||||||
byte[] actualTag = new byte[16];
|
byte[] actualTag = new byte[Constants.TAG_BYTES];
|
||||||
System.arraycopy(ciphertext, 0, actualTag, 0, 16);
|
System.arraycopy(ciphertext, 0, actualTag, 0, Constants.TAG_BYTES);
|
||||||
assertTrue(Arrays.equals(expectedTag, actualTag));
|
assertTrue(Arrays.equals(expectedTag, actualTag));
|
||||||
// Check the packet
|
// Check the packet
|
||||||
byte[] actualPacket = new byte[packet.length];
|
byte[] actualPacket = new byte[packet.length];
|
||||||
System.arraycopy(ciphertext, 16, actualPacket, 0, actualPacket.length);
|
System.arraycopy(ciphertext, Constants.TAG_BYTES, actualPacket, 0,
|
||||||
|
actualPacket.length);
|
||||||
assertTrue(Arrays.equals(expectedPacket, actualPacket));
|
assertTrue(Arrays.equals(expectedPacket, actualPacket));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,9 @@ public class PacketWriterImplTest extends TestCase {
|
|||||||
PacketEncrypter e = new NullPacketEncrypter(out);
|
PacketEncrypter e = new NullPacketEncrypter(out);
|
||||||
PacketWriter p = new PacketWriterImpl(e, mac, 0, 0L);
|
PacketWriter p = new PacketWriterImpl(e, mac, 0, 0L);
|
||||||
p.getOutputStream().write(0);
|
p.getOutputStream().write(0);
|
||||||
// There should be 16 zero bytes for the tag, 1 for the byte written
|
// There should be TAG_BYTES bytes for the tag, 1 byte for the write
|
||||||
assertTrue(Arrays.equals(new byte[17], out.toByteArray()));
|
assertTrue(Arrays.equals(new byte[Constants.TAG_BYTES + 1],
|
||||||
|
out.toByteArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -93,6 +94,7 @@ public class PacketWriterImplTest extends TestCase {
|
|||||||
+ "00000000" // 32 bits for the packet number
|
+ "00000000" // 32 bits for the packet number
|
||||||
+ "00000000" // 32 bits for the block number
|
+ "00000000" // 32 bits for the block number
|
||||||
);
|
);
|
||||||
|
assertEquals(Constants.TAG_BYTES, expectedTag.length);
|
||||||
byte[] expectedTag1 = StringUtils.fromHexString(
|
byte[] expectedTag1 = StringUtils.fromHexString(
|
||||||
"0000" // 16 bits reserved
|
"0000" // 16 bits reserved
|
||||||
+ "F00D" // 16 bits for the transport ID
|
+ "F00D" // 16 bits for the transport ID
|
||||||
@@ -100,6 +102,7 @@ public class PacketWriterImplTest extends TestCase {
|
|||||||
+ "00000001" // 32 bits for the packet number
|
+ "00000001" // 32 bits for the packet number
|
||||||
+ "00000000" // 32 bits for the block number
|
+ "00000000" // 32 bits for the block number
|
||||||
);
|
);
|
||||||
|
assertEquals(Constants.TAG_BYTES, expectedTag1.length);
|
||||||
// Calculate what the MAC on the first packet should be
|
// Calculate what the MAC on the first packet should be
|
||||||
mac.update(expectedTag);
|
mac.update(expectedTag);
|
||||||
mac.update((byte) 0);
|
mac.update((byte) 0);
|
||||||
@@ -119,24 +122,27 @@ public class PacketWriterImplTest extends TestCase {
|
|||||||
p.getOutputStream().write(0);
|
p.getOutputStream().write(0);
|
||||||
p.nextPacket();
|
p.nextPacket();
|
||||||
byte[] written = out.toByteArray();
|
byte[] written = out.toByteArray();
|
||||||
assertEquals(17 + expectedMac.length + 17 + expectedMac1.length,
|
assertEquals(Constants.TAG_BYTES + 1 + expectedMac.length
|
||||||
|
+ Constants.TAG_BYTES + 1 + expectedMac1.length,
|
||||||
written.length);
|
written.length);
|
||||||
// Check the first packet's tag
|
// Check the first packet's tag
|
||||||
byte[] actualTag = new byte[16];
|
byte[] actualTag = new byte[Constants.TAG_BYTES];
|
||||||
System.arraycopy(written, 0, actualTag, 0, 16);
|
System.arraycopy(written, 0, actualTag, 0, Constants.TAG_BYTES);
|
||||||
assertTrue(Arrays.equals(expectedTag, actualTag));
|
assertTrue(Arrays.equals(expectedTag, actualTag));
|
||||||
// Check the first packet's MAC
|
// Check the first packet's MAC
|
||||||
byte[] actualMac = new byte[expectedMac.length];
|
byte[] actualMac = new byte[expectedMac.length];
|
||||||
System.arraycopy(written, 17, actualMac, 0, actualMac.length);
|
System.arraycopy(written, Constants.TAG_BYTES + 1, actualMac, 0,
|
||||||
|
actualMac.length);
|
||||||
assertTrue(Arrays.equals(expectedMac, actualMac));
|
assertTrue(Arrays.equals(expectedMac, actualMac));
|
||||||
// Check the second packet's tag
|
// Check the second packet's tag
|
||||||
byte[] actualTag1 = new byte[16];
|
byte[] actualTag1 = new byte[Constants.TAG_BYTES];
|
||||||
System.arraycopy(written, 17 + expectedMac.length, actualTag1, 0, 16);
|
System.arraycopy(written, Constants.TAG_BYTES + 1 + expectedMac.length,
|
||||||
|
actualTag1, 0, Constants.TAG_BYTES);
|
||||||
assertTrue(Arrays.equals(expectedTag1, actualTag1));
|
assertTrue(Arrays.equals(expectedTag1, actualTag1));
|
||||||
// Check the second packet's MAC
|
// Check the second packet's MAC
|
||||||
byte[] actualMac1 = new byte[expectedMac1.length];
|
byte[] actualMac1 = new byte[expectedMac1.length];
|
||||||
System.arraycopy(written, 17 + expectedMac.length + 17, actualMac1, 0,
|
System.arraycopy(written, Constants.TAG_BYTES + 1 + expectedMac.length
|
||||||
actualMac1.length);
|
+ Constants.TAG_BYTES + 1, actualMac1, 0, actualMac1.length);
|
||||||
assertTrue(Arrays.equals(expectedMac1, actualMac1));
|
assertTrue(Arrays.equals(expectedMac1, actualMac1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user