mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 14:19:53 +01:00
Add transport keys for reintroduced contact.
This commit is contained in:
@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.FormatException;
|
|||||||
import org.briarproject.bramble.api.client.ClientHelper;
|
import org.briarproject.bramble.api.client.ClientHelper;
|
||||||
import org.briarproject.bramble.api.client.ContactGroupFactory;
|
import org.briarproject.bramble.api.client.ContactGroupFactory;
|
||||||
import org.briarproject.bramble.api.contact.Contact;
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
import org.briarproject.bramble.api.contact.ContactManager;
|
import org.briarproject.bramble.api.contact.ContactManager;
|
||||||
import org.briarproject.bramble.api.crypto.KeyPair;
|
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||||
import org.briarproject.bramble.api.crypto.PrivateKey;
|
import org.briarproject.bramble.api.crypto.PrivateKey;
|
||||||
@@ -449,31 +450,26 @@ class IntroduceeProtocolEngine
|
|||||||
s.getRemote().acceptTimestamp);
|
s.getRemote().acceptTimestamp);
|
||||||
if (timestamp == -1) throw new AssertionError();
|
if (timestamp == -1) throw new AssertionError();
|
||||||
|
|
||||||
Map<TransportId, KeySetId> keys = null;
|
ContactId contactId;
|
||||||
try {
|
try {
|
||||||
contactManager.addContact(txn, s.getRemote().author,
|
contactId = contactManager.addContact(txn, s.getRemote().author,
|
||||||
localAuthor.getId(), false);
|
localAuthor.getId(), false);
|
||||||
|
|
||||||
// Only add transport properties and keys when the contact was added
|
|
||||||
// This will be changed once we have a way to reset state for peers
|
|
||||||
// that were contacts already at some point in the past.
|
|
||||||
Contact c = contactManager.getContact(txn,
|
|
||||||
s.getRemote().author.getId(), localAuthor.getId());
|
|
||||||
|
|
||||||
// add the keys to the new contact
|
|
||||||
keys = keyManager.addRotationKeys(txn, c.getId(),
|
|
||||||
new SecretKey(s.getMasterKey()), timestamp,
|
|
||||||
s.getLocal().alice, false);
|
|
||||||
|
|
||||||
// add signed transport properties for the contact
|
// add signed transport properties for the contact
|
||||||
transportPropertyManager.addRemoteProperties(txn, c.getId(),
|
transportPropertyManager.addRemoteProperties(txn, contactId,
|
||||||
s.getRemote().transportProperties);
|
s.getRemote().transportProperties);
|
||||||
} catch (ContactExistsException e) {
|
} catch (ContactExistsException e) {
|
||||||
// Ignore this, because the other introducee might have deleted us.
|
// The other introducee might have deleted us and been
|
||||||
// So we still want updated transport properties
|
// reintroduced. In that case we can ignore the transport
|
||||||
// and new transport keys.
|
// properties, but we still want the new transport keys as the
|
||||||
|
// contact will no longer have the old keys
|
||||||
|
contactId = contactManager.getContact(txn,
|
||||||
|
s.getRemote().author.getId(), localAuthor.getId()).getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<TransportId, KeySetId> keys = keyManager.addRotationKeys(txn,
|
||||||
|
contactId, new SecretKey(s.getMasterKey()), timestamp,
|
||||||
|
s.getLocal().alice, false);
|
||||||
|
|
||||||
// send ACTIVATE message with a MAC
|
// send ACTIVATE message with a MAC
|
||||||
byte[] mac = crypto.activateMac(s);
|
byte[] mac = crypto.activateMac(s);
|
||||||
long localTimestamp = getTimestampForInvisibleMessage(s);
|
long localTimestamp = getTimestampForInvisibleMessage(s);
|
||||||
|
|||||||
@@ -1667,6 +1667,126 @@ public class IntroductionIntegrationTest
|
|||||||
assertTrue(deleteMessages0From1(emptySet()).allDeleted());
|
assertTrue(deleteMessages0From1(emptySet()).allDeleted());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReintroductionAfterBothIntroduceesDeleteEachOther()
|
||||||
|
throws Exception {
|
||||||
|
addListeners(true, true);
|
||||||
|
|
||||||
|
// Introduce 1 to 2
|
||||||
|
makeIntroduction(true);
|
||||||
|
updateContactIdsFor1And2();
|
||||||
|
|
||||||
|
// Sync client versions and transport properties - this shows that
|
||||||
|
// 1 and 2 share a set of transport keys
|
||||||
|
sync1To2(1, true);
|
||||||
|
sync2To1(1, true);
|
||||||
|
sync1To2(2, true);
|
||||||
|
sync2To1(1, true);
|
||||||
|
ack1To2(1);
|
||||||
|
|
||||||
|
// Both introducees delete each other
|
||||||
|
contactManager1.removeContact(contactId2From1);
|
||||||
|
contactManager2.removeContact(contactId1From2);
|
||||||
|
|
||||||
|
// Introduce 1 to 2 again
|
||||||
|
makeIntroduction(true);
|
||||||
|
updateContactIdsFor1And2();
|
||||||
|
|
||||||
|
// Sync client versions and transport properties again
|
||||||
|
sync1To2(1, true);
|
||||||
|
sync2To1(1, true);
|
||||||
|
sync1To2(2, true);
|
||||||
|
sync2To1(1, true);
|
||||||
|
ack1To2(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReintroductionAfterOneIntroduceeDeletesTheOther()
|
||||||
|
throws Exception {
|
||||||
|
addListeners(true, true);
|
||||||
|
|
||||||
|
// Introduce 1 to 2
|
||||||
|
makeIntroduction(true);
|
||||||
|
updateContactIdsFor1And2();
|
||||||
|
|
||||||
|
// Sync client versions and transport properties - this shows that
|
||||||
|
// 1 and 2 share a set of transport keys
|
||||||
|
sync1To2(1, true);
|
||||||
|
sync2To1(1, true);
|
||||||
|
sync1To2(2, true);
|
||||||
|
sync2To1(1, true);
|
||||||
|
ack1To2(1);
|
||||||
|
|
||||||
|
// 1 deletes 2, but not vice versa
|
||||||
|
contactManager1.removeContact(contactId2From1);
|
||||||
|
|
||||||
|
// Introduce 1 to 2 again
|
||||||
|
makeIntroduction(false);
|
||||||
|
updateContactIdsFor1And2();
|
||||||
|
|
||||||
|
// Sync client versioning update from 1 to 2 only - this shows that
|
||||||
|
// although 1 and 2 share transport keys, the connection won't be
|
||||||
|
// fully functional until we have a way for 1 to reset the state it's
|
||||||
|
// holding about 2
|
||||||
|
sync1To2(1, true);
|
||||||
|
ack2To1(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeIntroduction(boolean expectAddContact2From1)
|
||||||
|
throws Exception {
|
||||||
|
// Make introduction
|
||||||
|
Contact introducee1 = contact1From0;
|
||||||
|
Contact introducee2 = contact2From0;
|
||||||
|
introductionManager0.makeIntroduction(introducee1, introducee2, "Hi!");
|
||||||
|
|
||||||
|
// Request to 1
|
||||||
|
sync0To1(1, true);
|
||||||
|
eventWaiter.await(TIMEOUT, 1);
|
||||||
|
assertTrue(listener1.requestReceived);
|
||||||
|
|
||||||
|
// Request to 2
|
||||||
|
sync0To2(1, true);
|
||||||
|
eventWaiter.await(TIMEOUT, 1);
|
||||||
|
assertTrue(listener2.requestReceived);
|
||||||
|
|
||||||
|
// Response from 1, forwarded
|
||||||
|
sync1To0(1, true);
|
||||||
|
eventWaiter.await(TIMEOUT, 1);
|
||||||
|
assertTrue(listener0.response1Received);
|
||||||
|
sync0To2(1, true);
|
||||||
|
|
||||||
|
// Response and auth from 2, forwarded
|
||||||
|
sync2To0(2, true);
|
||||||
|
eventWaiter.await(TIMEOUT, 1);
|
||||||
|
assertTrue(listener0.response2Received);
|
||||||
|
sync0To1(2, true);
|
||||||
|
if (expectAddContact2From1) {
|
||||||
|
eventWaiter.await(TIMEOUT, 1);
|
||||||
|
assertTrue(listener1.succeeded);
|
||||||
|
}
|
||||||
|
assertTrue(contactManager1
|
||||||
|
.contactExists(author2.getId(), author1.getId()));
|
||||||
|
|
||||||
|
// Auth and activate from 1, forwarded
|
||||||
|
sync1To0(2, true);
|
||||||
|
sync0To2(2, true);
|
||||||
|
eventWaiter.await(TIMEOUT, 1);
|
||||||
|
assertTrue(listener2.succeeded);
|
||||||
|
assertTrue(contactManager2
|
||||||
|
.contactExists(author1.getId(), author2.getId()));
|
||||||
|
|
||||||
|
// Activate from 2, forwarded
|
||||||
|
sync2To0(1, true);
|
||||||
|
sync0To1(1, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateContactIdsFor1And2() throws Exception {
|
||||||
|
contactId2From1 = contactManager1.getContact(author2.getId(),
|
||||||
|
author1.getId()).getId();
|
||||||
|
contactId1From2 = contactManager2.getContact(author1.getId(),
|
||||||
|
author2.getId()).getId();
|
||||||
|
}
|
||||||
|
|
||||||
private DeletionResult deleteAllMessages1From0() throws DbException {
|
private DeletionResult deleteAllMessages1From0() throws DbException {
|
||||||
return db0.transactionWithResult(false, txn -> introductionManager0
|
return db0.transactionWithResult(false, txn -> introductionManager0
|
||||||
.deleteAllMessages(txn, contactId1From0));
|
.deleteAllMessages(txn, contactId1From0));
|
||||||
|
|||||||
Reference in New Issue
Block a user