Fixed some key derivation bugs and removed an unnecessary argument.

CryptoComponentImpl needs some unit tests.
This commit is contained in:
akwizgran
2012-03-29 20:11:11 +01:00
parent 15d7fd5796
commit b01b17f2b1
3 changed files with 11 additions and 17 deletions

View File

@@ -19,7 +19,7 @@ public interface CryptoComponent {
byte[][] deriveInitialSecrets(byte[] ourPublicKey, byte[] theirPublicKey, byte[][] deriveInitialSecrets(byte[] ourPublicKey, byte[] theirPublicKey,
PrivateKey ourPrivateKey, int invitationCode, boolean initiator); PrivateKey ourPrivateKey, int invitationCode, boolean initiator);
int deriveConfirmationCode(byte[] secret, boolean initiator); int deriveConfirmationCode(byte[] secret);
byte[] deriveNextSecret(byte[] secret, int index, long connection); byte[] deriveNextSecret(byte[] secret, int index, long connection);

View File

@@ -104,14 +104,14 @@ class CryptoComponentImpl implements CryptoComponent {
if(secret.length != SECRET_KEY_BYTES) if(secret.length != SECRET_KEY_BYTES)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
// The label and context must leave a byte free for the counter // The label and context must leave a byte free for the counter
if(label.length + context.length + 4 > KEY_DERIVATION_IV_BYTES) if(label.length + context.length + 2 >= KEY_DERIVATION_IV_BYTES)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
// The IV contains the length-prefixed label and context // The IV contains the length-prefixed label and context
byte[] ivBytes = new byte[KEY_DERIVATION_IV_BYTES]; byte[] ivBytes = new byte[KEY_DERIVATION_IV_BYTES];
ByteUtils.writeUint8(label.length, ivBytes, 0); ByteUtils.writeUint8(label.length, ivBytes, 0);
System.arraycopy(label, 0, ivBytes, 2, label.length); System.arraycopy(label, 0, ivBytes, 1, label.length);
ByteUtils.writeUint8(context.length, ivBytes, label.length + 2); ByteUtils.writeUint8(context.length, ivBytes, label.length + 1);
System.arraycopy(context, 0, ivBytes, label.length + 4, context.length); System.arraycopy(context, 0, ivBytes, label.length + 2, context.length);
// Use the secret and the IV to encrypt a blank plaintext // Use the secret and the IV to encrypt a blank plaintext
IvParameterSpec iv = new IvParameterSpec(ivBytes); IvParameterSpec iv = new IvParameterSpec(ivBytes);
ErasableKey key = new ErasableKeyImpl(secret, SECRET_KEY_ALGO); ErasableKey key = new ErasableKeyImpl(secret, SECRET_KEY_ALGO);
@@ -178,7 +178,7 @@ class CryptoComponentImpl implements CryptoComponent {
if(messageDigest.getDigestLength() < SECRET_KEY_BYTES) if(messageDigest.getDigestLength() < SECRET_KEY_BYTES)
throw new RuntimeException(); throw new RuntimeException();
// All fields are length-prefixed // All fields are length-prefixed
byte[] length = new byte[4]; byte[] length = new byte[1];
ByteUtils.writeUint8(rawSecret.length, length, 0); ByteUtils.writeUint8(rawSecret.length, length, 0);
messageDigest.update(length); messageDigest.update(length);
messageDigest.update(rawSecret); messageDigest.update(rawSecret);
@@ -213,19 +213,13 @@ class CryptoComponentImpl implements CryptoComponent {
return counterModeKdf(secret, NEXT, context); return counterModeKdf(secret, NEXT, context);
} }
public int deriveConfirmationCode(byte[] secret, boolean initiator) { public int deriveConfirmationCode(byte[] secret) {
byte[] context = initiator ? INITIATOR : RESPONDER; byte[] output = counterModeKdf(secret, CODE, CODE);
byte[] output = counterModeKdf(secret, CODE, context); int code = ByteUtils.readUint(output, CODE_BITS);
int code = extractCode(output);
ByteUtils.erase(output); ByteUtils.erase(output);
return code; return code;
} }
private int extractCode(byte[] secret) {
// Convert the first CODE_BITS bits of the secret into an unsigned int
return ByteUtils.readUint(secret, CODE_BITS);
}
public KeyPair generateKeyPair() { public KeyPair generateKeyPair() {
return keyPairGenerator.generateKeyPair(); return keyPairGenerator.generateKeyPair();
} }

View File

@@ -158,8 +158,8 @@ class InvitationStarterImpl implements InvitationStarter {
callback.showFailure(INVALID_KEY); callback.showFailure(INVALID_KEY);
return; return;
} }
int initCode = crypto.deriveConfirmationCode(secrets[0], true); int initCode = crypto.deriveConfirmationCode(secrets[0]);
int respCode = crypto.deriveConfirmationCode(secrets[1], false); int respCode = crypto.deriveConfirmationCode(secrets[1]);
int ourCode = initiator ? initCode : respCode; int ourCode = initiator ? initCode : respCode;
int theirCode = initiator ? respCode : initCode; int theirCode = initiator ? respCode : initCode;
// Compare the confirmation codes // Compare the confirmation codes