mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-14 03:39:05 +01:00
Derive handshake root key when converting pending contact.
This commit is contained in:
@@ -13,6 +13,7 @@ import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@@ -44,10 +45,13 @@ public interface ContactManager {
|
||||
* for each transport, and returns an ID for the contact.
|
||||
*
|
||||
* @param alice True if the local party is Alice
|
||||
* @throws GeneralSecurityException If the pending contact's handshake
|
||||
* public key is invalid
|
||||
*/
|
||||
ContactId addContact(Transaction txn, PendingContactId p, Author remote,
|
||||
AuthorId local, SecretKey rootKey, long timestamp, boolean alice,
|
||||
boolean verified, boolean active) throws DbException;
|
||||
boolean verified, boolean active)
|
||||
throws DbException, GeneralSecurityException;
|
||||
|
||||
/**
|
||||
* Stores a contact associated with the given local and remote pseudonyms
|
||||
@@ -83,9 +87,11 @@ public interface ContactManager {
|
||||
* @throws UnsupportedVersionException If the link uses a format version
|
||||
* that is not supported
|
||||
* @throws FormatException If the link is invalid
|
||||
* @throws GeneralSecurityException If the pending contact's handshake
|
||||
* public key is invalid
|
||||
*/
|
||||
PendingContact addPendingContact(String link, String alias)
|
||||
throws DbException, FormatException;
|
||||
throws DbException, FormatException, GeneralSecurityException;
|
||||
|
||||
/**
|
||||
* Returns the pending contact with the given ID.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
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.PublicKey;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
@@ -21,9 +21,9 @@ import javax.annotation.Nullable;
|
||||
public interface KeyManager {
|
||||
|
||||
/**
|
||||
* Informs the key manager that a new contact has been added. Derives and
|
||||
* stores a set of rotation mode transport keys for communicating with the
|
||||
* contact over each transport and returns the key set IDs.
|
||||
* Derives and stores a set of rotation mode transport keys for
|
||||
* communicating with the given contact over each transport and returns the
|
||||
* key set IDs.
|
||||
* <p/>
|
||||
* {@link StreamContext StreamContexts} for the contact can be created
|
||||
* after this method has returned.
|
||||
@@ -31,7 +31,7 @@ public interface KeyManager {
|
||||
* @param alice True if the local party is Alice
|
||||
* @param active Whether the derived keys can be used for outgoing streams
|
||||
*/
|
||||
Map<TransportId, KeySetId> addContactWithRotationKeys(Transaction txn,
|
||||
Map<TransportId, KeySetId> addRotationKeys(Transaction txn,
|
||||
ContactId c, SecretKey rootKey, long timestamp, boolean alice,
|
||||
boolean active) throws DbException;
|
||||
|
||||
@@ -42,11 +42,10 @@ public interface KeyManager {
|
||||
* <p/>
|
||||
* {@link StreamContext StreamContexts} for the contact can be created
|
||||
* after this method has returned.
|
||||
*
|
||||
* @param alice True if the local party is Alice
|
||||
*/
|
||||
Map<TransportId, KeySetId> addContactWithHandshakeKeys(Transaction txn,
|
||||
ContactId c, SecretKey rootKey, boolean alice) throws DbException;
|
||||
Map<TransportId, KeySetId> addContact(Transaction txn, ContactId c,
|
||||
PublicKey theirPublicKey, KeyPair ourKeyPair)
|
||||
throws DbException, GeneralSecurityException;
|
||||
|
||||
/**
|
||||
* Informs the key manager that a new pending contact has been added.
|
||||
@@ -58,7 +57,7 @@ public interface KeyManager {
|
||||
* created after this method has returned.
|
||||
*/
|
||||
Map<TransportId, KeySetId> addPendingContact(Transaction txn,
|
||||
PendingContact p, KeyPair ourKeyPair)
|
||||
PendingContactId p, PublicKey theirPublicKey, KeyPair ourKeyPair)
|
||||
throws DbException, GeneralSecurityException;
|
||||
|
||||
/**
|
||||
|
||||
@@ -78,8 +78,7 @@ class ContactManagerImpl implements ContactManager {
|
||||
SecretKey rootKey, long timestamp, boolean alice, boolean verified,
|
||||
boolean active) throws DbException {
|
||||
ContactId c = db.addContact(txn, remote, local, null, verified);
|
||||
keyManager.addContactWithRotationKeys(txn, c, rootKey, timestamp,
|
||||
alice, active);
|
||||
keyManager.addRotationKeys(txn, c, rootKey, timestamp, alice, active);
|
||||
Contact contact = db.getContact(txn, c);
|
||||
for (ContactHook hook : hooks) hook.addingContact(txn, contact);
|
||||
return c;
|
||||
@@ -89,12 +88,14 @@ class ContactManagerImpl implements ContactManager {
|
||||
public ContactId addContact(Transaction txn, PendingContactId p,
|
||||
Author remote, AuthorId local, SecretKey rootKey, long timestamp,
|
||||
boolean alice, boolean verified, boolean active)
|
||||
throws DbException {
|
||||
PublicKey handshake = db.getPendingContact(txn, p).getPublicKey();
|
||||
throws DbException, GeneralSecurityException {
|
||||
PublicKey theirPublicKey = db.getPendingContact(txn, p).getPublicKey();
|
||||
db.removePendingContact(txn, p);
|
||||
ContactId c = db.addContact(txn, remote, local, handshake, verified);
|
||||
keyManager.addContactWithRotationKeys(txn, c, rootKey, timestamp,
|
||||
alice, active);
|
||||
ContactId c =
|
||||
db.addContact(txn, remote, local, theirPublicKey, verified);
|
||||
KeyPair ourKeyPair = identityManager.getHandshakeKeys(txn);
|
||||
keyManager.addContact(txn, c, theirPublicKey, ourKeyPair);
|
||||
keyManager.addRotationKeys(txn, c, rootKey, timestamp, alice, active);
|
||||
Contact contact = db.getContact(txn, c);
|
||||
for (ContactHook hook : hooks) hook.addingContact(txn, contact);
|
||||
return c;
|
||||
@@ -126,18 +127,19 @@ class ContactManagerImpl implements ContactManager {
|
||||
|
||||
@Override
|
||||
public PendingContact addPendingContact(String link, String alias)
|
||||
throws DbException, FormatException {
|
||||
throws DbException, FormatException, GeneralSecurityException {
|
||||
PendingContact p =
|
||||
pendingContactFactory.createPendingContact(link, alias);
|
||||
db.transaction(false, txn -> {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.addPendingContact(txn, p);
|
||||
KeyPair ourKeyPair = identityManager.getHandshakeKeys(txn);
|
||||
try {
|
||||
keyManager.addPendingContact(txn, p, ourKeyPair);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
});
|
||||
keyManager.addPendingContact(txn, p.getId(), p.getPublicKey(),
|
||||
ourKeyPair);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
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.contact.event.PendingContactRemovedEvent;
|
||||
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.crypto.TransportCrypto;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
@@ -101,46 +101,51 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<TransportId, KeySetId> addContactWithRotationKeys(
|
||||
public Map<TransportId, KeySetId> addRotationKeys(
|
||||
Transaction txn, ContactId c, SecretKey rootKey, long timestamp,
|
||||
boolean alice, boolean active) throws DbException {
|
||||
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.addContactWithRotationKeys(txn, c, rootKey, timestamp,
|
||||
ids.put(t, m.addRotationKeys(txn, c, rootKey, timestamp,
|
||||
alice, active));
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<TransportId, KeySetId> addContactWithHandshakeKeys(
|
||||
Transaction txn, ContactId c, SecretKey rootKey, boolean alice)
|
||||
throws DbException {
|
||||
public Map<TransportId, KeySetId> addContact(Transaction txn, ContactId c,
|
||||
PublicKey theirPublicKey, KeyPair ourKeyPair)
|
||||
throws DbException, GeneralSecurityException {
|
||||
SecretKey staticMasterKey = transportCrypto
|
||||
.deriveStaticMasterKey(theirPublicKey, ourKeyPair);
|
||||
SecretKey rootKey =
|
||||
transportCrypto.deriveHandshakeRootKey(staticMasterKey, true);
|
||||
boolean alice = transportCrypto.isAlice(theirPublicKey, 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.addContactWithHandshakeKeys(txn, c, rootKey, alice));
|
||||
ids.put(t, m.addHandshakeKeys(txn, c, rootKey, alice));
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<TransportId, KeySetId> addPendingContact(Transaction txn,
|
||||
PendingContact p, KeyPair ourKeyPair)
|
||||
PendingContactId p, PublicKey theirPublicKey, KeyPair ourKeyPair)
|
||||
throws DbException, GeneralSecurityException {
|
||||
SecretKey staticMasterKey = transportCrypto
|
||||
.deriveStaticMasterKey(p.getPublicKey(), ourKeyPair);
|
||||
.deriveStaticMasterKey(theirPublicKey, ourKeyPair);
|
||||
SecretKey rootKey =
|
||||
transportCrypto.deriveHandshakeRootKey(staticMasterKey, true);
|
||||
boolean alice = transportCrypto.isAlice(p.getPublicKey(), ourKeyPair);
|
||||
boolean alice = transportCrypto.isAlice(theirPublicKey, 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.getId(), rootKey, alice));
|
||||
ids.put(t, m.addHandshakeKeys(txn, p, rootKey, alice));
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
@@ -16,14 +16,14 @@ interface TransportKeyManager {
|
||||
|
||||
void start(Transaction txn) throws DbException;
|
||||
|
||||
KeySetId addContactWithRotationKeys(Transaction txn, ContactId c,
|
||||
KeySetId addRotationKeys(Transaction txn, ContactId c,
|
||||
SecretKey rootKey, long timestamp, boolean alice, boolean active)
|
||||
throws DbException;
|
||||
|
||||
KeySetId addContactWithHandshakeKeys(Transaction txn, ContactId c,
|
||||
KeySetId addHandshakeKeys(Transaction txn, ContactId c,
|
||||
SecretKey rootKey, boolean alice) throws DbException;
|
||||
|
||||
KeySetId addPendingContact(Transaction txn, PendingContactId p,
|
||||
KeySetId addHandshakeKeys(Transaction txn, PendingContactId p,
|
||||
SecretKey rootKey, boolean alice) throws DbException;
|
||||
|
||||
void activateKeys(Transaction txn, KeySetId k) throws DbException;
|
||||
|
||||
@@ -115,11 +115,14 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
TransportKeys k = ks.getKeys();
|
||||
TransportKeys k1 = transportCrypto.updateTransportKeys(k,
|
||||
timePeriod);
|
||||
TransportKeySet ks1 = new TransportKeySet(ks.getKeySetId(),
|
||||
ks.getContactId(), null, k1);
|
||||
if (k1.getTimePeriod() > k.getTimePeriod())
|
||||
if (k1.getTimePeriod() > k.getTimePeriod()) {
|
||||
TransportKeySet ks1 = new TransportKeySet(ks.getKeySetId(),
|
||||
ks.getContactId(), ks.getPendingContactId(), k1);
|
||||
updateResult.updated.add(ks1);
|
||||
updateResult.current.add(ks1);
|
||||
updateResult.current.add(ks1);
|
||||
} else {
|
||||
updateResult.current.add(ks);
|
||||
}
|
||||
}
|
||||
return updateResult;
|
||||
}
|
||||
@@ -207,7 +210,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeySetId addContactWithRotationKeys(Transaction txn, ContactId c,
|
||||
public KeySetId addRotationKeys(Transaction txn, ContactId c,
|
||||
SecretKey rootKey, long timestamp, boolean alice, boolean active)
|
||||
throws DbException {
|
||||
lock.lock();
|
||||
@@ -222,7 +225,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
k = transportCrypto.updateTransportKeys(k, timePeriod);
|
||||
// Write the keys back to the DB
|
||||
KeySetId keySetId = db.addTransportKeys(txn, c, k);
|
||||
// Initialise mutable state for the contact
|
||||
// Initialise mutable state for the keys
|
||||
addKeys(keySetId, c, null, new MutableTransportKeys(k));
|
||||
return keySetId;
|
||||
} finally {
|
||||
@@ -231,7 +234,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeySetId addContactWithHandshakeKeys(Transaction txn, ContactId c,
|
||||
public KeySetId addHandshakeKeys(Transaction txn, ContactId c,
|
||||
SecretKey rootKey, boolean alice) throws DbException {
|
||||
lock.lock();
|
||||
try {
|
||||
@@ -242,7 +245,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
rootKey, timePeriod, alice);
|
||||
// Write the keys back to the DB
|
||||
KeySetId keySetId = db.addTransportKeys(txn, c, k);
|
||||
// Initialise mutable state for the contact
|
||||
// Initialise mutable state for the keys
|
||||
addKeys(keySetId, c, null, new MutableTransportKeys(k));
|
||||
return keySetId;
|
||||
} finally {
|
||||
@@ -251,7 +254,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeySetId addPendingContact(Transaction txn, PendingContactId p,
|
||||
public KeySetId addHandshakeKeys(Transaction txn, PendingContactId p,
|
||||
SecretKey rootKey, boolean alice) throws DbException {
|
||||
lock.lock();
|
||||
try {
|
||||
@@ -262,7 +265,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
rootKey, timePeriod, alice);
|
||||
// Write the keys back to the DB
|
||||
KeySetId keySetId = db.addTransportKeys(txn, p, k);
|
||||
// Initialise mutable state for the pending contact
|
||||
// Initialise mutable state for the keys
|
||||
addKeys(keySetId, null, p, new MutableTransportKeys(k));
|
||||
return keySetId;
|
||||
} finally {
|
||||
|
||||
@@ -73,8 +73,8 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
oneOf(db).transactionWithResult(with(false), withDbCallable(txn));
|
||||
oneOf(db).addContact(txn, remote, local, null, verified);
|
||||
will(returnValue(contactId));
|
||||
oneOf(keyManager).addContactWithRotationKeys(txn, contactId,
|
||||
rootKey, timestamp, alice, active);
|
||||
oneOf(keyManager).addRotationKeys(txn, contactId, rootKey,
|
||||
timestamp, alice, active);
|
||||
oneOf(db).getContact(txn, contactId);
|
||||
will(returnValue(contact));
|
||||
}});
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
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.PublicKey;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.crypto.TransportCrypto;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
@@ -31,8 +31,8 @@ import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENG
|
||||
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;
|
||||
@@ -52,8 +52,8 @@ public class KeyManagerImplTest extends BrambleMockTestCase {
|
||||
private final DeterministicExecutor executor = new DeterministicExecutor();
|
||||
private final Transaction txn = new Transaction(null, false);
|
||||
private final ContactId contactId = getContactId();
|
||||
private final PendingContact pendingContact = getPendingContact();
|
||||
private final PendingContactId pendingContactId = pendingContact.getId();
|
||||
private final PendingContactId pendingContactId =
|
||||
new PendingContactId(getRandomId());
|
||||
private final KeySetId keySetId = new KeySetId(345);
|
||||
private final TransportId transportId = getTransportId();
|
||||
private final TransportId unknownTransportId = getTransportId();
|
||||
@@ -64,6 +64,11 @@ public class KeyManagerImplTest extends BrambleMockTestCase {
|
||||
new StreamContext(null, pendingContactId, transportId,
|
||||
getSecretKey(), getSecretKey(), 1, true);
|
||||
private final byte[] tag = getRandomBytes(TAG_LENGTH);
|
||||
private final PublicKey theirPublicKey = getAgreementPublicKey();
|
||||
private final KeyPair ourKeyPair =
|
||||
new KeyPair(getAgreementPublicKey(), getAgreementPrivateKey());
|
||||
private final SecretKey staticMasterKey = getSecretKey();
|
||||
private final SecretKey rootKey = getSecretKey();
|
||||
private final Random random = new Random();
|
||||
|
||||
private final KeyManagerImpl keyManager = new KeyManagerImpl(db, executor,
|
||||
@@ -105,57 +110,59 @@ public class KeyManagerImplTest extends BrambleMockTestCase {
|
||||
boolean active = random.nextBoolean();
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(transportKeyManager).addContactWithRotationKeys(txn,
|
||||
oneOf(transportKeyManager).addRotationKeys(txn,
|
||||
contactId, secretKey, timestamp, alice, active);
|
||||
will(returnValue(keySetId));
|
||||
}});
|
||||
|
||||
Map<TransportId, KeySetId> ids = keyManager.addContactWithRotationKeys(
|
||||
Map<TransportId, KeySetId> ids = keyManager.addRotationKeys(
|
||||
txn, contactId, secretKey, timestamp, alice, active);
|
||||
assertEquals(singletonMap(transportId, keySetId), ids);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddContactWithHandshakeModeKeys() throws Exception {
|
||||
SecretKey secretKey = getSecretKey();
|
||||
public void testAddContactWithHandshakePublicKey() throws Exception {
|
||||
boolean alice = random.nextBoolean();
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(transportKeyManager).addContactWithHandshakeKeys(
|
||||
txn, contactId, secretKey, alice);
|
||||
oneOf(transportCrypto)
|
||||
.deriveStaticMasterKey(theirPublicKey, ourKeyPair);
|
||||
will(returnValue(staticMasterKey));
|
||||
oneOf(transportCrypto)
|
||||
.deriveHandshakeRootKey(staticMasterKey, false);
|
||||
will(returnValue(rootKey));
|
||||
oneOf(transportCrypto).isAlice(theirPublicKey, ourKeyPair);
|
||||
will(returnValue(alice));
|
||||
oneOf(transportKeyManager).addHandshakeKeys(txn, contactId,
|
||||
rootKey, alice);
|
||||
will(returnValue(keySetId));
|
||||
}});
|
||||
|
||||
Map<TransportId, KeySetId> ids = keyManager.addContactWithHandshakeKeys(
|
||||
txn, contactId, secretKey, alice);
|
||||
Map<TransportId, KeySetId> ids = keyManager.addContact(txn, contactId,
|
||||
theirPublicKey, ourKeyPair);
|
||||
assertEquals(singletonMap(transportId, keySetId), ids);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddPendingContact() throws Exception {
|
||||
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);
|
||||
oneOf(transportCrypto)
|
||||
.deriveStaticMasterKey(theirPublicKey, ourKeyPair);
|
||||
will(returnValue(staticMasterKey));
|
||||
oneOf(transportCrypto)
|
||||
.deriveHandshakeRootKey(staticMasterKey, true);
|
||||
will(returnValue(rootKey));
|
||||
oneOf(transportCrypto).isAlice(pendingContact.getPublicKey(),
|
||||
ourKeyPair);
|
||||
oneOf(transportCrypto).isAlice(theirPublicKey, ourKeyPair);
|
||||
will(returnValue(alice));
|
||||
oneOf(transportKeyManager).addPendingContact(txn, pendingContactId,
|
||||
oneOf(transportKeyManager).addHandshakeKeys(txn, pendingContactId,
|
||||
rootKey, alice);
|
||||
will(returnValue(keySetId));
|
||||
}});
|
||||
|
||||
Map<TransportId, KeySetId> ids = keyManager.addPendingContact(txn,
|
||||
pendingContact, ourKeyPair);
|
||||
pendingContactId, theirPublicKey, ourKeyPair);
|
||||
assertEquals(singletonMap(transportId, keySetId), ids);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.hamcrest.Description;
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.api.Action;
|
||||
import org.jmock.api.Invocation;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -72,6 +73,14 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||
private final SecretKey rootKey = getSecretKey();
|
||||
private final Random random = new Random();
|
||||
|
||||
private TransportKeyManager transportKeyManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
transportKeyManager = new TransportKeyManagerImpl(db, transportCrypto,
|
||||
dbExecutor, scheduler, clock, transportId, maxLatency);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeysAreUpdatedAtStartup() throws Exception {
|
||||
boolean active = random.nextBoolean();
|
||||
@@ -112,16 +121,13 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||
with(timePeriodLength - 1), with(MILLISECONDS));
|
||||
}});
|
||||
|
||||
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
||||
maxLatency);
|
||||
transportKeyManager.start(txn);
|
||||
assertEquals(active,
|
||||
transportKeyManager.canSendOutgoingStreams(contactId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRotationKeysAreDerivedAndUpdatedWhenAddingContact()
|
||||
public void testRotationKeysForContactAreDerivedAndUpdatedWhenAdded()
|
||||
throws Exception {
|
||||
boolean alice = random.nextBoolean();
|
||||
boolean active = random.nextBoolean();
|
||||
@@ -156,14 +162,14 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||
maxLatency);
|
||||
// The timestamp is 1 ms before the start of time period 1000
|
||||
long timestamp = timePeriodLength * 1000 - 1;
|
||||
assertEquals(keySetId, transportKeyManager.addContactWithRotationKeys(
|
||||
txn, contactId, rootKey, timestamp, alice, active));
|
||||
assertEquals(keySetId, transportKeyManager.addRotationKeys(txn,
|
||||
contactId, rootKey, timestamp, alice, active));
|
||||
assertEquals(active,
|
||||
transportKeyManager.canSendOutgoingStreams(contactId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandshakeKeysAreDerivedWhenAddingContact()
|
||||
public void testHandshakeKeysForContactAreDerivedWhenAdded()
|
||||
throws Exception {
|
||||
boolean alice = random.nextBoolean();
|
||||
TransportKeys transportKeys = createHandshakeKeys(1000, 0, alice);
|
||||
@@ -189,16 +195,13 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||
will(returnValue(keySetId));
|
||||
}});
|
||||
|
||||
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
||||
maxLatency);
|
||||
assertEquals(keySetId, transportKeyManager.addContactWithHandshakeKeys(
|
||||
txn, contactId, rootKey, alice));
|
||||
assertEquals(keySetId, transportKeyManager.addHandshakeKeys(txn,
|
||||
contactId, rootKey, alice));
|
||||
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandshakeKeysAreDerivedWhenAddingPendingContact()
|
||||
public void testHandshakeKeysForPendingContactAreDerivedWhenAdded()
|
||||
throws Exception {
|
||||
boolean alice = random.nextBoolean();
|
||||
TransportKeys transportKeys = createHandshakeKeys(1000, 0, alice);
|
||||
@@ -224,10 +227,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||
will(returnValue(keySetId));
|
||||
}});
|
||||
|
||||
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
||||
maxLatency);
|
||||
assertEquals(keySetId, transportKeyManager.addPendingContact(txn,
|
||||
assertEquals(keySetId, transportKeyManager.addHandshakeKeys(txn,
|
||||
pendingContactId, rootKey, alice));
|
||||
assertTrue(transportKeyManager.canSendOutgoingStreams(
|
||||
pendingContactId));
|
||||
@@ -269,12 +269,9 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||
|
||||
expectAddContactKeysNotUpdated(alice, true, transportKeys, txn);
|
||||
|
||||
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
||||
maxLatency);
|
||||
// The timestamp is at the start of time period 1000
|
||||
long timestamp = timePeriodLength * 1000;
|
||||
assertEquals(keySetId, transportKeyManager.addContactWithRotationKeys(
|
||||
assertEquals(keySetId, transportKeyManager.addRotationKeys(
|
||||
txn, contactId, rootKey, timestamp, alice, true));
|
||||
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
||||
@@ -295,12 +292,9 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||
oneOf(db).incrementStreamCounter(txn, transportId, keySetId);
|
||||
}});
|
||||
|
||||
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
||||
maxLatency);
|
||||
// The timestamp is at the start of time period 1000
|
||||
long timestamp = timePeriodLength * 1000;
|
||||
assertEquals(keySetId, transportKeyManager.addContactWithRotationKeys(
|
||||
assertEquals(keySetId, transportKeyManager.addRotationKeys(
|
||||
txn, contactId, rootKey, timestamp, alice, true));
|
||||
// The first request should return a stream context
|
||||
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||
@@ -327,12 +321,9 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||
|
||||
expectAddContactKeysNotUpdated(alice, active, transportKeys, txn);
|
||||
|
||||
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
||||
maxLatency);
|
||||
// The timestamp is at the start of time period 1000
|
||||
long timestamp = timePeriodLength * 1000;
|
||||
assertEquals(keySetId, transportKeyManager.addContactWithRotationKeys(
|
||||
assertEquals(keySetId, transportKeyManager.addRotationKeys(
|
||||
txn, contactId, rootKey, timestamp, alice, active));
|
||||
assertEquals(active,
|
||||
transportKeyManager.canSendOutgoingStreams(contactId));
|
||||
@@ -380,12 +371,9 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||
1, new byte[REORDERING_WINDOW_SIZE / 8]);
|
||||
}});
|
||||
|
||||
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
||||
maxLatency);
|
||||
// The timestamp is at the start of time period 1000
|
||||
long timestamp = timePeriodLength * 1000;
|
||||
assertEquals(keySetId, transportKeyManager.addContactWithRotationKeys(
|
||||
assertEquals(keySetId, transportKeyManager.addRotationKeys(
|
||||
txn, contactId, rootKey, timestamp, alice, true));
|
||||
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||
// Use the first tag (previous time period, stream number 0)
|
||||
@@ -461,9 +449,6 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||
with(timePeriodLength), with(MILLISECONDS));
|
||||
}});
|
||||
|
||||
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
||||
maxLatency);
|
||||
transportKeyManager.start(txn);
|
||||
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||
}
|
||||
@@ -483,12 +468,9 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||
oneOf(db).incrementStreamCounter(txn, transportId, keySetId);
|
||||
}});
|
||||
|
||||
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
||||
maxLatency);
|
||||
// The timestamp is at the start of time period 1000
|
||||
long timestamp = timePeriodLength * 1000;
|
||||
assertEquals(keySetId, transportKeyManager.addContactWithRotationKeys(
|
||||
assertEquals(keySetId, transportKeyManager.addRotationKeys(
|
||||
txn, contactId, rootKey, timestamp, alice, false));
|
||||
// The keys are inactive so no stream context should be returned
|
||||
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||
@@ -549,12 +531,9 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||
oneOf(db).incrementStreamCounter(txn, transportId, keySetId);
|
||||
}});
|
||||
|
||||
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
||||
maxLatency);
|
||||
// The timestamp is at the start of time period 1000
|
||||
long timestamp = timePeriodLength * 1000;
|
||||
assertEquals(keySetId, transportKeyManager.addContactWithRotationKeys(
|
||||
assertEquals(keySetId, transportKeyManager.addRotationKeys(
|
||||
txn, contactId, rootKey, timestamp, alice, false));
|
||||
// The keys are inactive so no stream context should be returned
|
||||
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.briarproject.briar.android.viewmodel.LiveEvent;
|
||||
import org.briarproject.briar.android.viewmodel.LiveResult;
|
||||
import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -102,14 +103,15 @@ public class AddContactViewModel extends AndroidViewModel {
|
||||
} catch (UnsupportedVersionException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
addContactResult.postValue(new LiveResult<>(e));
|
||||
} catch (DbException | FormatException e) {
|
||||
} catch (DbException | FormatException
|
||||
| GeneralSecurityException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
addContactResult.postValue(new LiveResult<>(e));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public LiveData<LiveResult<Boolean>> getAddContactResult() {
|
||||
LiveData<LiveResult<Boolean>> getAddContactResult() {
|
||||
return addContactResult;
|
||||
}
|
||||
|
||||
|
||||
@@ -444,7 +444,7 @@ class IntroduceeProtocolEngine
|
||||
|
||||
// add the keys to the new contact
|
||||
//noinspection ConstantConditions
|
||||
keys = keyManager.addContactWithRotationKeys(txn, c.getId(),
|
||||
keys = keyManager.addRotationKeys(txn, c.getId(),
|
||||
new SecretKey(s.getMasterKey()), timestamp,
|
||||
s.getLocal().alice, false);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user