mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Derive handshake root key when adding a pending contact.
This commit is contained in:
@@ -11,6 +11,12 @@ import java.security.GeneralSecurityException;
|
||||
*/
|
||||
public interface TransportCrypto {
|
||||
|
||||
/**
|
||||
* Returns true if the local peer is Alice.
|
||||
*/
|
||||
boolean isAlice(PublicKey theirHandshakePublicKey,
|
||||
KeyPair ourHandshakeKeyPair);
|
||||
|
||||
/**
|
||||
* Derives the static master key shared with a contact or pending contact.
|
||||
*/
|
||||
@@ -19,6 +25,7 @@ public interface TransportCrypto {
|
||||
|
||||
/**
|
||||
* Derives the handshake mode root key from the static master key.
|
||||
*
|
||||
* @param pendingContact Whether the static master key is shared with a
|
||||
* pending contact or a contact
|
||||
*/
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package org.briarproject.bramble.api.transport;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.contact.PendingContact;
|
||||
import org.briarproject.bramble.api.contact.PendingContactId;
|
||||
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.plugin.TransportId;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@@ -53,12 +56,10 @@ public interface KeyManager {
|
||||
* <p/>
|
||||
* {@link StreamContext StreamContexts} for the pending contact can be
|
||||
* created after this method has returned.
|
||||
*
|
||||
* @param alice True if the local party is Alice
|
||||
*/
|
||||
Map<TransportId, KeySetId> addPendingContact(Transaction txn,
|
||||
PendingContactId p, SecretKey rootKey, boolean alice)
|
||||
throws DbException;
|
||||
PendingContact p, KeyPair ourKeyPair)
|
||||
throws DbException, GeneralSecurityException;
|
||||
|
||||
/**
|
||||
* Marks the given transport keys as usable for outgoing streams.
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.contact.PendingContact;
|
||||
import org.briarproject.bramble.api.contact.PendingContactId;
|
||||
import org.briarproject.bramble.api.contact.PendingContactState;
|
||||
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
@@ -21,6 +22,7 @@ import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.transport.KeyManager;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -51,6 +53,7 @@ class ContactManagerImpl implements ContactManager {
|
||||
private final KeyManager keyManager;
|
||||
private final IdentityManager identityManager;
|
||||
private final PendingContactFactory pendingContactFactory;
|
||||
|
||||
private final List<ContactHook> hooks;
|
||||
|
||||
@Inject
|
||||
@@ -123,7 +126,15 @@ class ContactManagerImpl implements ContactManager {
|
||||
throws DbException, FormatException {
|
||||
PendingContact p =
|
||||
pendingContactFactory.createPendingContact(link, alias);
|
||||
db.transaction(false, txn -> db.addPendingContact(txn, p));
|
||||
db.transaction(false, txn -> {
|
||||
db.addPendingContact(txn, p);
|
||||
KeyPair ourKeyPair = identityManager.getHandshakeKeys(txn);
|
||||
try {
|
||||
keyManager.addPendingContact(txn, p, ourKeyPair);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
});
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,14 @@ class TransportCryptoImpl implements TransportCrypto {
|
||||
this.crypto = crypto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlice(PublicKey theirHandshakePublicKey,
|
||||
KeyPair ourHandshakeKeyPair) {
|
||||
byte[] theirPublic = theirHandshakePublicKey.getEncoded();
|
||||
byte[] ourPublic = ourHandshakeKeyPair.getPublic().getEncoded();
|
||||
return compare(ourPublic, theirPublic) < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretKey deriveStaticMasterKey(PublicKey theirHandshakePublicKey,
|
||||
KeyPair ourHandshakeKeyPair) throws GeneralSecurityException {
|
||||
@@ -55,8 +63,8 @@ class TransportCryptoImpl implements TransportCrypto {
|
||||
byte[] ourPublic = ourHandshakeKeyPair.getPublic().getEncoded();
|
||||
boolean alice = compare(ourPublic, theirPublic) < 0;
|
||||
byte[][] inputs = {
|
||||
alice ? ourPublic : theirPublic,
|
||||
alice ? theirPublic : ourPublic
|
||||
alice ? ourPublic : theirPublic,
|
||||
alice ? theirPublic : ourPublic
|
||||
};
|
||||
return crypto.deriveSharedSecret(STATIC_MASTER_KEY_LABEL,
|
||||
theirHandshakePublicKey, ourHandshakeKeyPair, inputs);
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package org.briarproject.bramble.transport;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.contact.PendingContact;
|
||||
import org.briarproject.bramble.api.contact.PendingContactId;
|
||||
import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
|
||||
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.crypto.TransportCrypto;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
@@ -21,6 +24,7 @@ import org.briarproject.bramble.api.transport.KeyManager;
|
||||
import org.briarproject.bramble.api.transport.KeySetId;
|
||||
import org.briarproject.bramble.api.transport.StreamContext;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -46,17 +50,22 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
||||
private final Executor dbExecutor;
|
||||
private final PluginConfig pluginConfig;
|
||||
private final TransportKeyManagerFactory transportKeyManagerFactory;
|
||||
private final TransportCrypto transportCrypto;
|
||||
|
||||
private final ConcurrentHashMap<TransportId, TransportKeyManager> managers;
|
||||
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||
|
||||
@Inject
|
||||
KeyManagerImpl(DatabaseComponent db, @DatabaseExecutor Executor dbExecutor,
|
||||
KeyManagerImpl(DatabaseComponent db,
|
||||
@DatabaseExecutor Executor dbExecutor,
|
||||
PluginConfig pluginConfig,
|
||||
TransportKeyManagerFactory transportKeyManagerFactory) {
|
||||
TransportKeyManagerFactory transportKeyManagerFactory,
|
||||
TransportCrypto transportCrypto) {
|
||||
this.db = db;
|
||||
this.dbExecutor = dbExecutor;
|
||||
this.pluginConfig = pluginConfig;
|
||||
this.transportKeyManagerFactory = transportKeyManagerFactory;
|
||||
this.transportCrypto = transportCrypto;
|
||||
managers = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@@ -118,13 +127,18 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
||||
|
||||
@Override
|
||||
public Map<TransportId, KeySetId> addPendingContact(Transaction txn,
|
||||
PendingContactId p, SecretKey rootKey, boolean alice)
|
||||
throws DbException {
|
||||
PendingContact p, KeyPair ourKeyPair)
|
||||
throws DbException, GeneralSecurityException {
|
||||
SecretKey staticMasterKey = transportCrypto
|
||||
.deriveStaticMasterKey(p.getPublicKey(), ourKeyPair);
|
||||
SecretKey rootKey =
|
||||
transportCrypto.deriveHandshakeRootKey(staticMasterKey, true);
|
||||
boolean alice = transportCrypto.isAlice(p.getPublicKey(), ourKeyPair);
|
||||
Map<TransportId, KeySetId> ids = new HashMap<>();
|
||||
for (Entry<TransportId, TransportKeyManager> e : managers.entrySet()) {
|
||||
TransportId t = e.getKey();
|
||||
TransportKeyManager m = e.getValue();
|
||||
ids.put(t, m.addPendingContact(txn, p, rootKey, alice));
|
||||
ids.put(t, m.addPendingContact(txn, p.getId(), rootKey, alice));
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package org.briarproject.bramble.transport;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.contact.PendingContact;
|
||||
import org.briarproject.bramble.api.contact.PendingContactId;
|
||||
import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
|
||||
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.crypto.TransportCrypto;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.plugin.PluginConfig;
|
||||
@@ -25,9 +28,11 @@ import java.util.Random;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static org.briarproject.bramble.test.TestUtils.getAgreementPrivateKey;
|
||||
import static org.briarproject.bramble.test.TestUtils.getAgreementPublicKey;
|
||||
import static org.briarproject.bramble.test.TestUtils.getContactId;
|
||||
import static org.briarproject.bramble.test.TestUtils.getPendingContact;
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||
import static org.briarproject.bramble.test.TestUtils.getTransportId;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -41,12 +46,14 @@ public class KeyManagerImplTest extends BrambleMockTestCase {
|
||||
context.mock(TransportKeyManagerFactory.class);
|
||||
private final TransportKeyManager transportKeyManager =
|
||||
context.mock(TransportKeyManager.class);
|
||||
private final TransportCrypto transportCrypto =
|
||||
context.mock(TransportCrypto.class);
|
||||
|
||||
private final DeterministicExecutor executor = new DeterministicExecutor();
|
||||
private final Transaction txn = new Transaction(null, false);
|
||||
private final ContactId contactId = getContactId();
|
||||
private final PendingContactId pendingContactId =
|
||||
new PendingContactId(getRandomId());
|
||||
private final PendingContact pendingContact = getPendingContact();
|
||||
private final PendingContactId pendingContactId = pendingContact.getId();
|
||||
private final KeySetId keySetId = new KeySetId(345);
|
||||
private final TransportId transportId = getTransportId();
|
||||
private final TransportId unknownTransportId = getTransportId();
|
||||
@@ -60,7 +67,7 @@ public class KeyManagerImplTest extends BrambleMockTestCase {
|
||||
private final Random random = new Random();
|
||||
|
||||
private final KeyManagerImpl keyManager = new KeyManagerImpl(db, executor,
|
||||
pluginConfig, transportKeyManagerFactory);
|
||||
pluginConfig, transportKeyManagerFactory, transportCrypto);
|
||||
|
||||
@Before
|
||||
public void testStartService() throws Exception {
|
||||
@@ -126,17 +133,29 @@ public class KeyManagerImplTest extends BrambleMockTestCase {
|
||||
|
||||
@Test
|
||||
public void testAddPendingContact() throws Exception {
|
||||
SecretKey secretKey = getSecretKey();
|
||||
KeyPair ourKeyPair =
|
||||
new KeyPair(getAgreementPublicKey(), getAgreementPrivateKey());
|
||||
SecretKey staticMasterKey = getSecretKey();
|
||||
SecretKey rootKey = getSecretKey();
|
||||
boolean alice = random.nextBoolean();
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(transportCrypto).deriveStaticMasterKey(
|
||||
pendingContact.getPublicKey(), ourKeyPair);
|
||||
will(returnValue(staticMasterKey));
|
||||
oneOf(transportCrypto)
|
||||
.deriveHandshakeRootKey(staticMasterKey, true);
|
||||
will(returnValue(rootKey));
|
||||
oneOf(transportCrypto).isAlice(pendingContact.getPublicKey(),
|
||||
ourKeyPair);
|
||||
will(returnValue(alice));
|
||||
oneOf(transportKeyManager).addPendingContact(txn, pendingContactId,
|
||||
secretKey, alice);
|
||||
rootKey, alice);
|
||||
will(returnValue(keySetId));
|
||||
}});
|
||||
|
||||
Map<TransportId, KeySetId> ids = keyManager.addPendingContact(txn,
|
||||
pendingContactId, secretKey, alice);
|
||||
pendingContact, ourKeyPair);
|
||||
assertEquals(singletonMap(transportId, keySetId), ids);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user