mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 19:29:06 +01:00
Length prefix all KDF arguments.
This commit is contained in:
@@ -43,15 +43,15 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
private static final String FRAME_CIPHER_ALGO = "AES/CTR/NoPadding";
|
||||
private static final String MAC_ALGO = "HMacSHA384";
|
||||
|
||||
// Labels for key derivation, null-terminated
|
||||
private static final byte[] TAG = { 'T', 'A', 'G', 0 };
|
||||
private static final byte[] FRAME = { 'F', 'R', 'A', 'M', 'E', 0 };
|
||||
private static final byte[] MAC = { 'M', 'A', 'C', 0 };
|
||||
// Labels for secret derivation, null-terminated
|
||||
private static final byte[] FIRST = { 'F', 'I', 'R', 'S', 'T', 0 };
|
||||
private static final byte[] NEXT = { 'N', 'E', 'X', 'T', 0 };
|
||||
// Label for confirmation code derivation, null-terminated
|
||||
private static final byte[] CODE = { 'C', 'O', 'D', 'E', 0 };
|
||||
// Labels for key derivation
|
||||
private static final byte[] TAG = { 'T', 'A', 'G' };
|
||||
private static final byte[] FRAME = { 'F', 'R', 'A', 'M', 'E' };
|
||||
private static final byte[] MAC = { 'M', 'A', 'C' };
|
||||
// Labels for secret derivation
|
||||
private static final byte[] FIRST = { 'F', 'I', 'R', 'S', 'T' };
|
||||
private static final byte[] NEXT = { 'N', 'E', 'X', 'T' };
|
||||
// Label for confirmation code derivation
|
||||
private static final byte[] CODE = { 'C', 'O', 'D', 'E' };
|
||||
// Context strings for key and confirmation code derivation
|
||||
private static final byte[] INITIATOR = { 'I' };
|
||||
private static final byte[] RESPONDER = { 'R' };
|
||||
@@ -103,18 +103,14 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
// The secret must be usable as a key
|
||||
if(secret.length != SECRET_KEY_BYTES)
|
||||
throw new IllegalArgumentException();
|
||||
// The label string must be null-terminated
|
||||
for(int i = 0; i < label.length - 1; i++)
|
||||
if(label[i] == 0) throw new IllegalArgumentException();
|
||||
if(label[label.length - 1] != 0) throw new IllegalArgumentException();
|
||||
// The label and context must leave a byte free for the counter
|
||||
if(label.length + context.length + 5 > KEY_DERIVATION_IV_BYTES)
|
||||
if(label.length + context.length + 4 > KEY_DERIVATION_IV_BYTES)
|
||||
throw new IllegalArgumentException();
|
||||
// The IV starts with the null-terminated label
|
||||
// The IV contains the length-prefixed label and context
|
||||
byte[] ivBytes = new byte[KEY_DERIVATION_IV_BYTES];
|
||||
System.arraycopy(label, 0, ivBytes, 0, label.length);
|
||||
// Next comes the length-prefixed context
|
||||
ByteUtils.writeUint32(context.length, ivBytes, label.length);
|
||||
ByteUtils.writeUint8(label.length, ivBytes, 0);
|
||||
System.arraycopy(label, 0, ivBytes, 2, label.length);
|
||||
ByteUtils.writeUint8(context.length, ivBytes, label.length + 2);
|
||||
System.arraycopy(context, 0, ivBytes, label.length + 4, context.length);
|
||||
// Use the secret and the IV to encrypt a blank plaintext
|
||||
IvParameterSpec iv = new IvParameterSpec(ivBytes);
|
||||
@@ -138,8 +134,7 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
MessageDigest messageDigest = getMessageDigest();
|
||||
byte[] ourHash = messageDigest.digest(ourPublicKey);
|
||||
byte[] theirHash = messageDigest.digest(theirPublicKey);
|
||||
// The initiator and responder info for the concatenation KDF are
|
||||
// the hashes of the corresponding public keys
|
||||
// The initiator and responder info are hashes of the public keys
|
||||
byte[] initiatorInfo, responderInfo;
|
||||
if(initiator) {
|
||||
initiatorInfo = ourHash;
|
||||
@@ -148,8 +143,7 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
initiatorInfo = theirHash;
|
||||
responderInfo = ourHash;
|
||||
}
|
||||
// The public info for the concatenation KDF is the invitation code
|
||||
// as a uint32
|
||||
// The public info is the invitation code as a uint32
|
||||
byte[] publicInfo = new byte[4];
|
||||
ByteUtils.writeUint32(invitationCode, publicInfo, 0);
|
||||
// The raw secret comes from the key agreement algorithm
|
||||
@@ -183,23 +177,21 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
MessageDigest messageDigest = getMessageDigest();
|
||||
if(messageDigest.getDigestLength() < SECRET_KEY_BYTES)
|
||||
throw new RuntimeException();
|
||||
// The label string must be null-terminated
|
||||
for(int i = 0; i < label.length - 1; i++)
|
||||
if(label[i] == 0) throw new IllegalArgumentException();
|
||||
if(label[label.length - 1] != 0) throw new IllegalArgumentException();
|
||||
// All other fields are length-prefixed
|
||||
// All fields are length-prefixed
|
||||
byte[] length = new byte[4];
|
||||
ByteUtils.writeUint32(rawSecret.length, length, 0);
|
||||
ByteUtils.writeUint8(rawSecret.length, length, 0);
|
||||
messageDigest.update(length);
|
||||
messageDigest.update(rawSecret);
|
||||
ByteUtils.writeUint8(label.length, length, 0);
|
||||
messageDigest.update(length);
|
||||
messageDigest.update(label);
|
||||
ByteUtils.writeUint32(initiatorInfo.length, length, 0);
|
||||
ByteUtils.writeUint8(initiatorInfo.length, length, 0);
|
||||
messageDigest.update(length);
|
||||
messageDigest.update(initiatorInfo);
|
||||
ByteUtils.writeUint32(responderInfo.length, length, 0);
|
||||
ByteUtils.writeUint8(responderInfo.length, length, 0);
|
||||
messageDigest.update(length);
|
||||
messageDigest.update(responderInfo);
|
||||
ByteUtils.writeUint32(publicInfo.length, length, 0);
|
||||
ByteUtils.writeUint8(publicInfo.length, length, 0);
|
||||
messageDigest.update(length);
|
||||
messageDigest.update(publicInfo);
|
||||
byte[] hash = messageDigest.digest();
|
||||
|
||||
@@ -12,10 +12,17 @@ public class ByteUtils {
|
||||
*/
|
||||
public static final long MAX_32_BIT_UNSIGNED = 4294967295L; // 2^32 - 1
|
||||
|
||||
public static void writeUint8(int i, byte[] b, int offset) {
|
||||
if(i < 0) throw new IllegalArgumentException();
|
||||
if(i > 255) throw new IllegalArgumentException();
|
||||
if(b.length < offset) throw new IllegalArgumentException();
|
||||
b[offset] = (byte) i;
|
||||
}
|
||||
|
||||
public static void writeUint16(int i, byte[] b, int offset) {
|
||||
if(i < 0) throw new IllegalArgumentException();
|
||||
if(i > MAX_16_BIT_UNSIGNED) throw new IllegalArgumentException();
|
||||
assert b.length >= offset + 2;
|
||||
if(b.length < offset + 2) throw new IllegalArgumentException();
|
||||
b[offset] = (byte) (i >> 8);
|
||||
b[offset + 1] = (byte) (i & 0xFF);
|
||||
}
|
||||
@@ -23,7 +30,7 @@ public class ByteUtils {
|
||||
public static void writeUint32(long i, byte[] b, int offset) {
|
||||
if(i < 0L) throw new IllegalArgumentException();
|
||||
if(i > MAX_32_BIT_UNSIGNED) throw new IllegalArgumentException();
|
||||
assert b.length >= offset + 4;
|
||||
if(b.length < offset + 4) throw new IllegalArgumentException();
|
||||
b[offset] = (byte) (i >> 24);
|
||||
b[offset + 1] = (byte) (i >> 16 & 0xFF);
|
||||
b[offset + 2] = (byte) (i >> 8 & 0xFF);
|
||||
|
||||
Reference in New Issue
Block a user