diff --git a/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java b/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java index 3ee032a58f0f38b324c2ecebb40a3f038157c1b9..dc594a4f6f5561322501beec1447da019a501306 100644 --- a/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java +++ b/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java @@ -244,7 +244,7 @@ implements InvitationListener { int getLocalInvitationCode() { if (localInvitationCode == -1) - localInvitationCode = crypto.generateInvitationCode(); + localInvitationCode = crypto.generateBTInvitationCode(); return localInvitationCode; } diff --git a/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java b/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java index 836628c906a9cd997cf300ab10711454876aaa42..65b12c961cb45cef1796c3a128845520535d34cc 100644 --- a/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java +++ b/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java @@ -27,35 +27,35 @@ public interface CryptoComponent { KeyParser getSignatureKeyParser(); /** Generates a random invitation code. */ - int generateInvitationCode(); + int generateBTInvitationCode(); /** * Derives a shared master secret from two public keys and one of the * corresponding private keys. * @param alice whether the private key belongs to Alice or Bob. */ - SecretKey deriveMasterSecret(byte[] theirPublicKey, KeyPair ourKeyPair, + SecretKey deriveBTMasterSecret(byte[] theirPublicKey, KeyPair ourKeyPair, boolean alice) throws GeneralSecurityException; /** * Derives a confirmation code from the given master secret. * @param alice whether the code is for use by Alice or Bob. */ - int deriveConfirmationCode(SecretKey master, boolean alice); + int deriveBTConfirmationCode(SecretKey master, boolean alice); /** * Derives a header key for an invitation stream from the given master * secret. * @param alice whether the key is for use by Alice or Bob. */ - SecretKey deriveInvitationKey(SecretKey master, boolean alice); + SecretKey deriveBTInvitationKey(SecretKey master, boolean alice); /** * Derives a nonce from the given master secret for one of the parties to * sign. * @param alice whether the nonce is for use by Alice or Bob. */ - byte[] deriveSignatureNonce(SecretKey master, boolean alice); + byte[] deriveBTSignatureNonce(SecretKey master, boolean alice); /** * Derives initial transport keys for the given transport in the given diff --git a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java index 4decd40839d9bb1a95551ebc8bcafb90eae33120..79759d995bbb218bb543bdc01c2c285704faa3ce 100644 --- a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java +++ b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java @@ -62,17 +62,17 @@ class CryptoComponentImpl implements CryptoComponent { return s.getBytes(Charset.forName("US-ASCII")); } - // KDF label for master key derivation - private static final byte[] MASTER = ascii("MASTER"); - // KDF labels for confirmation code derivation - private static final byte[] A_CONFIRM = ascii("ALICE_CONFIRMATION_CODE"); - private static final byte[] B_CONFIRM = ascii("BOB_CONFIRMATION_CODE"); - // KDF labels for invitation stream header key derivation - private static final byte[] A_INVITE = ascii("ALICE_INVITATION_KEY"); - private static final byte[] B_INVITE = ascii("BOB_INVITATION_KEY"); - // KDF labels for signature nonce derivation - private static final byte[] A_NONCE = ascii("ALICE_SIGNATURE_NONCE"); - private static final byte[] B_NONCE = ascii("BOB_SIGNATURE_NONCE"); + // KDF label for bluetooth master key derivation + private static final byte[] BT_MASTER = ascii("MASTER"); + // KDF labels for bluetooth confirmation code derivation + private static final byte[] BT_A_CONFIRM = ascii("ALICE_CONFIRMATION_CODE"); + private static final byte[] BT_B_CONFIRM = ascii("BOB_CONFIRMATION_CODE"); + // KDF labels for bluetooth invitation stream header key derivation + private static final byte[] BT_A_INVITE = ascii("ALICE_INVITATION_KEY"); + private static final byte[] BT_B_INVITE = ascii("BOB_INVITATION_KEY"); + // KDF labels for bluetooth signature nonce derivation + private static final byte[] BT_A_NONCE = ascii("ALICE_SIGNATURE_NONCE"); + private static final byte[] BT_B_NONCE = ascii("BOB_SIGNATURE_NONCE"); // KDF labels for tag key derivation private static final byte[] A_TAG = ascii("ALICE_TAG_KEY"); private static final byte[] B_TAG = ascii("BOB_TAG_KEY"); @@ -128,6 +128,25 @@ class CryptoComponentImpl implements CryptoComponent { return secureRandom; } + // Package access for testing + byte[] performRawKeyAgreement(PrivateKey priv, PublicKey pub) + throws GeneralSecurityException { + if (!(priv instanceof Sec1PrivateKey)) + throw new IllegalArgumentException(); + if (!(pub instanceof Sec1PublicKey)) + throw new IllegalArgumentException(); + ECPrivateKeyParameters ecPriv = ((Sec1PrivateKey) priv).getKey(); + ECPublicKeyParameters ecPub = ((Sec1PublicKey) pub).getKey(); + long now = System.currentTimeMillis(); + ECDHCBasicAgreement agreement = new ECDHCBasicAgreement(); + agreement.init(ecPriv); + byte[] secret = agreement.calculateAgreement(ecPub).toByteArray(); + long duration = System.currentTimeMillis() - now; + if (LOG.isLoggable(INFO)) + LOG.info("Deriving shared secret took " + duration + " ms"); + return secret; + } + public Signature getSignature() { return new SignatureImpl(secureRandom); } @@ -170,14 +189,14 @@ class CryptoComponentImpl implements CryptoComponent { return signatureKeyParser; } - public int generateInvitationCode() { + public int generateBTInvitationCode() { int codeBytes = (CODE_BITS + 7) / 8; byte[] random = new byte[codeBytes]; secureRandom.nextBytes(random); return ByteUtils.readUint(random, CODE_BITS); } - public SecretKey deriveMasterSecret(byte[] theirPublicKey, + public SecretKey deriveBTMasterSecret(byte[] theirPublicKey, KeyPair ourKeyPair, boolean alice) throws GeneralSecurityException { MessageDigest messageDigest = getMessageDigest(); byte[] ourPublicKey = ourKeyPair.getPublic().getEncoded(); @@ -194,41 +213,22 @@ class CryptoComponentImpl implements CryptoComponent { PrivateKey ourPriv = ourKeyPair.getPrivate(); PublicKey theirPub = agreementKeyParser.parsePublicKey(theirPublicKey); // The raw secret comes from the key agreement algorithm - byte[] raw = deriveSharedSecret(ourPriv, theirPub); + byte[] raw = performRawKeyAgreement(ourPriv, theirPub); // Derive the master secret from the raw secret using the hash KDF - return new SecretKey(hashKdf(raw, MASTER, aliceInfo, bobInfo)); - } - - // Package access for testing - byte[] deriveSharedSecret(PrivateKey priv, PublicKey pub) - throws GeneralSecurityException { - if (!(priv instanceof Sec1PrivateKey)) - throw new IllegalArgumentException(); - if (!(pub instanceof Sec1PublicKey)) - throw new IllegalArgumentException(); - ECPrivateKeyParameters ecPriv = ((Sec1PrivateKey) priv).getKey(); - ECPublicKeyParameters ecPub = ((Sec1PublicKey) pub).getKey(); - long now = System.currentTimeMillis(); - ECDHCBasicAgreement agreement = new ECDHCBasicAgreement(); - agreement.init(ecPriv); - byte[] secret = agreement.calculateAgreement(ecPub).toByteArray(); - long duration = System.currentTimeMillis() - now; - if (LOG.isLoggable(INFO)) - LOG.info("Deriving shared secret took " + duration + " ms"); - return secret; + return new SecretKey(hashKdf(raw, BT_MASTER, aliceInfo, bobInfo)); } - public int deriveConfirmationCode(SecretKey master, boolean alice) { - byte[] b = macKdf(master, alice ? A_CONFIRM : B_CONFIRM); + public int deriveBTConfirmationCode(SecretKey master, boolean alice) { + byte[] b = macKdf(master, alice ? BT_A_CONFIRM : BT_B_CONFIRM); return ByteUtils.readUint(b, CODE_BITS); } - public SecretKey deriveInvitationKey(SecretKey master, boolean alice) { - return new SecretKey(macKdf(master, alice ? A_INVITE : B_INVITE)); + public SecretKey deriveBTInvitationKey(SecretKey master, boolean alice) { + return new SecretKey(macKdf(master, alice ? BT_A_INVITE : BT_B_INVITE)); } - public byte[] deriveSignatureNonce(SecretKey master, boolean alice) { - return macKdf(master, alice ? A_NONCE : B_NONCE); + public byte[] deriveBTSignatureNonce(SecretKey master, boolean alice) { + return macKdf(master, alice ? BT_A_NONCE : BT_B_NONCE); } public TransportKeys deriveTransportKeys(TransportId t, diff --git a/briar-core/src/org/briarproject/invitation/AliceConnector.java b/briar-core/src/org/briarproject/invitation/AliceConnector.java index 7d7807b80f14d433d8ae89cfe394e4b33c445cd5..47c7b0a16d9868c7047b9e9a7e5e9176cf839993 100644 --- a/briar-core/src/org/briarproject/invitation/AliceConnector.java +++ b/briar-core/src/org/briarproject/invitation/AliceConnector.java @@ -93,8 +93,8 @@ class AliceConnector extends Connector { } // The key agreement succeeded - derive the confirmation codes if (LOG.isLoggable(INFO)) LOG.info(pluginName + " agreement succeeded"); - int aliceCode = crypto.deriveConfirmationCode(master, true); - int bobCode = crypto.deriveConfirmationCode(master, false); + int aliceCode = crypto.deriveBTConfirmationCode(master, true); + int bobCode = crypto.deriveBTConfirmationCode(master, false); group.keyAgreementSucceeded(aliceCode, bobCode); // Exchange confirmation results boolean localMatched, remoteMatched; @@ -128,8 +128,8 @@ class AliceConnector extends Connector { if (LOG.isLoggable(INFO)) LOG.info(pluginName + " confirmation succeeded"); // Derive the header keys - SecretKey aliceHeaderKey = crypto.deriveInvitationKey(master, true); - SecretKey bobHeaderKey = crypto.deriveInvitationKey(master, false); + SecretKey aliceHeaderKey = crypto.deriveBTInvitationKey(master, true); + SecretKey bobHeaderKey = crypto.deriveBTInvitationKey(master, false); // Create the readers InputStream streamReader = streamReaderFactory.createInvitationStreamReader(in, @@ -141,8 +141,8 @@ class AliceConnector extends Connector { aliceHeaderKey); w = bdfWriterFactory.createWriter(streamWriter); // Derive the invitation nonces - byte[] aliceNonce = crypto.deriveSignatureNonce(master, true); - byte[] bobNonce = crypto.deriveSignatureNonce(master, false); + byte[] aliceNonce = crypto.deriveBTSignatureNonce(master, true); + byte[] bobNonce = crypto.deriveBTSignatureNonce(master, false); // Exchange pseudonyms, signed nonces, and timestamps Author remoteAuthor; long remoteTimestamp; diff --git a/briar-core/src/org/briarproject/invitation/BobConnector.java b/briar-core/src/org/briarproject/invitation/BobConnector.java index 84e0f2987957bfc76c64d7fae4840bcee72f6260..945c56d1c6a07fe1fca6f5b35244f5e8f4c187ec 100644 --- a/briar-core/src/org/briarproject/invitation/BobConnector.java +++ b/briar-core/src/org/briarproject/invitation/BobConnector.java @@ -93,8 +93,8 @@ class BobConnector extends Connector { } // The key agreement succeeded - derive the confirmation codes if (LOG.isLoggable(INFO)) LOG.info(pluginName + " agreement succeeded"); - int aliceCode = crypto.deriveConfirmationCode(master, true); - int bobCode = crypto.deriveConfirmationCode(master, false); + int aliceCode = crypto.deriveBTConfirmationCode(master, true); + int bobCode = crypto.deriveBTConfirmationCode(master, false); group.keyAgreementSucceeded(bobCode, aliceCode); // Exchange confirmation results boolean localMatched, remoteMatched; @@ -128,8 +128,8 @@ class BobConnector extends Connector { if (LOG.isLoggable(INFO)) LOG.info(pluginName + " confirmation succeeded"); // Derive the header keys - SecretKey aliceHeaderKey = crypto.deriveInvitationKey(master, true); - SecretKey bobHeaderKey = crypto.deriveInvitationKey(master, false); + SecretKey aliceHeaderKey = crypto.deriveBTInvitationKey(master, true); + SecretKey bobHeaderKey = crypto.deriveBTInvitationKey(master, false); // Create the readers InputStream streamReader = streamReaderFactory.createInvitationStreamReader(in, @@ -141,8 +141,8 @@ class BobConnector extends Connector { bobHeaderKey); w = bdfWriterFactory.createWriter(streamWriter); // Derive the nonces - byte[] aliceNonce = crypto.deriveSignatureNonce(master, true); - byte[] bobNonce = crypto.deriveSignatureNonce(master, false); + byte[] aliceNonce = crypto.deriveBTSignatureNonce(master, true); + byte[] bobNonce = crypto.deriveBTSignatureNonce(master, false); // Exchange pseudonyms, signed nonces and timestamps Author remoteAuthor; long remoteTimestamp; diff --git a/briar-core/src/org/briarproject/invitation/Connector.java b/briar-core/src/org/briarproject/invitation/Connector.java index a89aef88a5b50fa9ec1d7d15a7646f4d50adc9c3..1a5ca82fba9168acb97a2c4875c4a36018a13dcf 100644 --- a/briar-core/src/org/briarproject/invitation/Connector.java +++ b/briar-core/src/org/briarproject/invitation/Connector.java @@ -146,7 +146,7 @@ abstract class Connector extends Thread { // Derive the master secret if (LOG.isLoggable(INFO)) LOG.info(pluginName + " deriving master secret"); - return crypto.deriveMasterSecret(key, keyPair, alice); + return crypto.deriveBTMasterSecret(key, keyPair, alice); } protected void sendConfirmation(BdfWriter w, boolean confirmed) diff --git a/briar-tests/src/org/briarproject/crypto/KeyAgreementTest.java b/briar-tests/src/org/briarproject/crypto/KeyAgreementTest.java index 732e638725723ee9e192de69f5dd525d25bad0a3..1544638c32dfe88b76a422758015f0ddafb60b07 100644 --- a/briar-tests/src/org/briarproject/crypto/KeyAgreementTest.java +++ b/briar-tests/src/org/briarproject/crypto/KeyAgreementTest.java @@ -13,15 +13,15 @@ import static org.junit.Assert.assertArrayEquals; public class KeyAgreementTest extends BriarTestCase { @Test - public void testKeyAgreement() throws Exception { + public void testBTKeyAgreement() throws Exception { SeedProvider seedProvider = new TestSeedProvider(); CryptoComponent crypto = new CryptoComponentImpl(seedProvider); KeyPair aPair = crypto.generateAgreementKeyPair(); byte[] aPub = aPair.getPublic().getEncoded(); KeyPair bPair = crypto.generateAgreementKeyPair(); byte[] bPub = bPair.getPublic().getEncoded(); - SecretKey aMaster = crypto.deriveMasterSecret(aPub, bPair, true); - SecretKey bMaster = crypto.deriveMasterSecret(bPub, aPair, false); + SecretKey aMaster = crypto.deriveBTMasterSecret(aPub, bPair, true); + SecretKey bMaster = crypto.deriveBTMasterSecret(bPub, aPair, false); assertArrayEquals(aMaster.getBytes(), bMaster.getBytes()); } } diff --git a/briar-tests/src/org/briarproject/crypto/KeyEncodingAndParsingTest.java b/briar-tests/src/org/briarproject/crypto/KeyEncodingAndParsingTest.java index b380dee5279864f5301ecf29b47bd50ba4c94a95..556deb17147ee850b78c96120297887bac4606d9 100644 --- a/briar-tests/src/org/briarproject/crypto/KeyEncodingAndParsingTest.java +++ b/briar-tests/src/org/briarproject/crypto/KeyEncodingAndParsingTest.java @@ -27,12 +27,12 @@ public class KeyEncodingAndParsingTest extends BriarTestCase { KeyPair bPair = crypto.generateAgreementKeyPair(); // Derive the shared secret PublicKey aPub = aPair.getPublic(); - byte[] secret = crypto.deriveSharedSecret(bPair.getPrivate(), aPub); + byte[] secret = crypto.performRawKeyAgreement(bPair.getPrivate(), aPub); // Encode and parse the public key - no exceptions should be thrown aPub = parser.parsePublicKey(aPub.getEncoded()); aPub = parser.parsePublicKey(aPub.getEncoded()); // Derive the shared secret again - it should be the same - byte[] secret1 = crypto.deriveSharedSecret(bPair.getPrivate(), aPub); + byte[] secret1 = crypto.performRawKeyAgreement(bPair.getPrivate(), aPub); assertArrayEquals(secret, secret1); } @@ -44,12 +44,12 @@ public class KeyEncodingAndParsingTest extends BriarTestCase { KeyPair bPair = crypto.generateAgreementKeyPair(); // Derive the shared secret PrivateKey bPriv = bPair.getPrivate(); - byte[] secret = crypto.deriveSharedSecret(bPriv, aPair.getPublic()); + byte[] secret = crypto.performRawKeyAgreement(bPriv, aPair.getPublic()); // Encode and parse the private key - no exceptions should be thrown bPriv = parser.parsePrivateKey(bPriv.getEncoded()); bPriv = parser.parsePrivateKey(bPriv.getEncoded()); // Derive the shared secret again - it should be the same - byte[] secret1 = crypto.deriveSharedSecret(bPriv, aPair.getPublic()); + byte[] secret1 = crypto.performRawKeyAgreement(bPriv, aPair.getPublic()); assertArrayEquals(secret, secret1); } @@ -90,12 +90,12 @@ public class KeyEncodingAndParsingTest extends BriarTestCase { KeyPair bPair = crypto.generateSignatureKeyPair(); // Derive the shared secret PublicKey aPub = aPair.getPublic(); - byte[] secret = crypto.deriveSharedSecret(bPair.getPrivate(), aPub); + byte[] secret = crypto.performRawKeyAgreement(bPair.getPrivate(), aPub); // Encode and parse the public key - no exceptions should be thrown aPub = parser.parsePublicKey(aPub.getEncoded()); aPub = parser.parsePublicKey(aPub.getEncoded()); // Derive the shared secret again - it should be the same - byte[] secret1 = crypto.deriveSharedSecret(bPair.getPrivate(), aPub); + byte[] secret1 = crypto.performRawKeyAgreement(bPair.getPrivate(), aPub); assertArrayEquals(secret, secret1); } @@ -107,12 +107,12 @@ public class KeyEncodingAndParsingTest extends BriarTestCase { KeyPair bPair = crypto.generateSignatureKeyPair(); // Derive the shared secret PrivateKey bPriv = bPair.getPrivate(); - byte[] secret = crypto.deriveSharedSecret(bPriv, aPair.getPublic()); + byte[] secret = crypto.performRawKeyAgreement(bPriv, aPair.getPublic()); // Encode and parse the private key - no exceptions should be thrown bPriv = parser.parsePrivateKey(bPriv.getEncoded()); bPriv = parser.parsePrivateKey(bPriv.getEncoded()); // Derive the shared secret again - it should be the same - byte[] secret1 = crypto.deriveSharedSecret(bPriv, aPair.getPublic()); + byte[] secret1 = crypto.performRawKeyAgreement(bPriv, aPair.getPublic()); assertArrayEquals(secret, secret1); }