diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/TransportCrypto.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/TransportCrypto.java
index 6385d1f01..cbd6449b4 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/TransportCrypto.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/TransportCrypto.java
@@ -14,9 +14,10 @@ public interface TransportCrypto {
* rotation period from the given master secret.
*
* @param alice whether the keys are for use by Alice or Bob.
+ * @param active whether the keys are usable for outgoing streams.
*/
TransportKeys deriveTransportKeys(TransportId t, SecretKey master,
- long rotationPeriod, boolean alice);
+ long rotationPeriod, boolean alice, boolean active);
/**
* Rotates the given transport keys to the given rotation period. If the
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java
index fcf5efe46..27e379571 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java
@@ -528,6 +528,12 @@ public interface DatabaseComponent {
void setReorderingWindow(Transaction txn, KeySetId k, TransportId t,
long rotationPeriod, long base, byte[] bitmap) throws DbException;
+ /**
+ * Marks the given transport keys as usable for outgoing streams.
+ */
+ void setTransportKeysActive(Transaction txn, TransportId t, KeySetId k)
+ throws DbException;
+
/**
* Stores the given transport keys, deleting any keys they have replaced.
*/
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/transport/KeyManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/KeyManager.java
index 06b2f4725..a3f0f6d60 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/transport/KeyManager.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/KeyManager.java
@@ -30,6 +30,9 @@ public interface KeyManager {
/**
* Derives and stores a set of unbound transport keys for each transport
* and returns the key set IDs.
+ *
+ * The keys must be bound before they can be used for incoming streams,
+ * and also activated before they can be used for outgoing streams.
*/
Map addUnboundKeys(Transaction txn, SecretKey master,
long timestamp, boolean alice) throws DbException;
@@ -40,6 +43,13 @@ public interface KeyManager {
void bindKeys(Transaction txn, ContactId c, Map keys)
throws DbException;
+ /**
+ * Marks the given transport keys as usable for outgoing streams. Keys must
+ * be bound before they are activated.
+ */
+ void activateKeys(Transaction txn, Map keys)
+ throws DbException;
+
/**
* Removes the given transport keys, which must not have been bound, from
* the manager and the database.
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/transport/OutgoingKeys.java b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/OutgoingKeys.java
index 202c46e6a..4214ffd91 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/transport/OutgoingKeys.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/OutgoingKeys.java
@@ -10,18 +10,20 @@ public class OutgoingKeys {
private final SecretKey tagKey, headerKey;
private final long rotationPeriod, streamCounter;
+ private final boolean active;
public OutgoingKeys(SecretKey tagKey, SecretKey headerKey,
- long rotationPeriod) {
- this(tagKey, headerKey, rotationPeriod, 0);
+ long rotationPeriod, boolean active) {
+ this(tagKey, headerKey, rotationPeriod, 0, active);
}
public OutgoingKeys(SecretKey tagKey, SecretKey headerKey,
- long rotationPeriod, long streamCounter) {
+ long rotationPeriod, long streamCounter, boolean active) {
this.tagKey = tagKey;
this.headerKey = headerKey;
this.rotationPeriod = rotationPeriod;
this.streamCounter = streamCounter;
+ this.active = active;
}
public SecretKey getTagKey() {
@@ -39,4 +41,8 @@ public class OutgoingKeys {
public long getStreamCounter() {
return streamCounter;
}
+
+ public boolean isActive() {
+ return active;
+ }
}
\ No newline at end of file
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/TransportCryptoImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/TransportCryptoImpl.java
index db35c9d5e..2d4ffb7d3 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/TransportCryptoImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/TransportCryptoImpl.java
@@ -36,7 +36,8 @@ class TransportCryptoImpl implements TransportCrypto {
@Override
public TransportKeys deriveTransportKeys(TransportId t,
- SecretKey master, long rotationPeriod, boolean alice) {
+ SecretKey master, long rotationPeriod, boolean alice,
+ boolean active) {
// Keys for the previous period are derived from the master secret
SecretKey inTagPrev = deriveTagKey(master, t, !alice);
SecretKey inHeaderPrev = deriveHeaderKey(master, t, !alice);
@@ -57,7 +58,7 @@ class TransportCryptoImpl implements TransportCrypto {
IncomingKeys inNext = new IncomingKeys(inTagNext, inHeaderNext,
rotationPeriod + 1);
OutgoingKeys outCurr = new OutgoingKeys(outTagCurr, outHeaderCurr,
- rotationPeriod);
+ rotationPeriod, active);
// Collect and return the keys
return new TransportKeys(t, inPrev, inCurr, inNext, outCurr);
}
@@ -71,6 +72,7 @@ class TransportCryptoImpl implements TransportCrypto {
IncomingKeys inNext = k.getNextIncomingKeys();
OutgoingKeys outCurr = k.getCurrentOutgoingKeys();
long startPeriod = outCurr.getRotationPeriod();
+ boolean active = outCurr.isActive();
// Rotate the keys
for (long p = startPeriod + 1; p <= rotationPeriod; p++) {
inPrev = inCurr;
@@ -80,7 +82,7 @@ class TransportCryptoImpl implements TransportCrypto {
inNext = new IncomingKeys(inNextTag, inNextHeader, p + 1);
SecretKey outCurrTag = rotateKey(outCurr.getTagKey(), p);
SecretKey outCurrHeader = rotateKey(outCurr.getHeaderKey(), p);
- outCurr = new OutgoingKeys(outCurrTag, outCurrHeader, p);
+ outCurr = new OutgoingKeys(outCurrTag, outCurrHeader, p, active);
}
// Collect and return the keys
return new TransportKeys(k.getTransportId(), inPrev, inCurr, inNext,
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java
index 6ee996b2b..ddd4860c2 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java
@@ -640,6 +640,12 @@ interface Database {
void setReorderingWindow(T txn, KeySetId k, TransportId t,
long rotationPeriod, long base, byte[] bitmap) throws DbException;
+ /**
+ * Marks the given transport keys as usable for outgoing streams.
+ */
+ void setTransportKeysActive(T txn, TransportId t, KeySetId k)
+ throws DbException;
+
/**
* Updates the transmission count and expiry time of the given message
* with respect to the given contact, using the latency of the transport
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java
index 697bcdd3d..a97480200 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java
@@ -890,6 +890,16 @@ class DatabaseComponentImpl implements DatabaseComponent {
db.setReorderingWindow(txn, k, t, rotationPeriod, base, bitmap);
}
+ @Override
+ public void setTransportKeysActive(Transaction transaction, TransportId t,
+ KeySetId k) throws DbException {
+ if (transaction.isReadOnly()) throw new IllegalArgumentException();
+ T txn = unbox(transaction);
+ if (!db.containsTransport(txn, t))
+ throw new NoSuchTransportException();
+ db.setTransportKeysActive(txn, t, k);
+ }
+
@Override
public void updateTransportKeys(Transaction transaction,
Collection keys) throws DbException {
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java
index 25cfb4d5a..953a0f160 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java
@@ -234,6 +234,7 @@ abstract class JdbcDatabase implements Database {
+ " tagKey _SECRET NOT NULL,"
+ " headerKey _SECRET NOT NULL,"
+ " stream BIGINT NOT NULL,"
+ + " active BOOLEAN NOT NULL,"
+ " PRIMARY KEY (transportId, keySetId),"
+ " FOREIGN KEY (transportId)"
+ " REFERENCES transports (transportId)"
@@ -880,8 +881,8 @@ abstract class JdbcDatabase implements Database {
try {
// Store the outgoing keys
String sql = "INSERT INTO outgoingKeys (contactId, transportId,"
- + " rotationPeriod, tagKey, headerKey, stream)"
- + " VALUES (?, ?, ?, ?, ?, ?)";
+ + " rotationPeriod, tagKey, headerKey, stream, active)"
+ + " VALUES (?, ?, ?, ?, ?, ?, ?)";
ps = txn.prepareStatement(sql);
if (c == null) ps.setNull(1, INTEGER);
else ps.setInt(1, c.getInt());
@@ -891,6 +892,7 @@ abstract class JdbcDatabase implements Database {
ps.setBytes(4, outCurr.getTagKey().getBytes());
ps.setBytes(5, outCurr.getHeaderKey().getBytes());
ps.setLong(6, outCurr.getStreamCounter());
+ ps.setBoolean(7, outCurr.isActive());
int affected = ps.executeUpdate();
if (affected != 1) throw new DbStateException();
ps.close();
@@ -2157,7 +2159,7 @@ abstract class JdbcDatabase implements Database {
ps.close();
// Retrieve the outgoing keys in the same order
sql = "SELECT keySetId, contactId, rotationPeriod,"
- + " tagKey, headerKey, stream"
+ + " tagKey, headerKey, stream, active"
+ " FROM outgoingKeys"
+ " WHERE transportId = ?"
+ " ORDER BY keySetId";
@@ -2175,8 +2177,9 @@ abstract class JdbcDatabase implements Database {
SecretKey tagKey = new SecretKey(rs.getBytes(4));
SecretKey headerKey = new SecretKey(rs.getBytes(5));
long streamCounter = rs.getLong(6);
+ boolean active = rs.getBoolean(7);
OutgoingKeys outCurr = new OutgoingKeys(tagKey, headerKey,
- rotationPeriod, streamCounter);
+ rotationPeriod, streamCounter, active);
IncomingKeys inPrev = inKeys.get(i * 3);
IncomingKeys inCurr = inKeys.get(i * 3 + 1);
IncomingKeys inNext = inKeys.get(i * 3 + 2);
@@ -2889,6 +2892,23 @@ abstract class JdbcDatabase implements Database {
}
}
+ @Override
+ public void setTransportKeysActive(Connection txn, TransportId t,
+ KeySetId k) throws DbException {
+ PreparedStatement ps = null;
+ try {
+ String sql = "UPDATE outgoingKeys SET active = true"
+ + " WHERE transportId = ? AND keySetId = ?";
+ ps = txn.prepareStatement(sql);
+ int affected = ps.executeUpdate();
+ if (affected < 0 || affected > 1) throw new DbStateException();
+ ps.close();
+ } catch (SQLException e) {
+ tryToClose(ps);
+ throw new DbException(e);
+ }
+ }
+
@Override
public void updateExpiryTime(Connection txn, ContactId c, MessageId m,
int maxLatency) throws DbException {
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/KeyManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/KeyManagerImpl.java
index 1a06ef4a6..860e0e402 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/transport/KeyManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/KeyManagerImpl.java
@@ -132,6 +132,20 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
}
}
+ @Override
+ public void activateKeys(Transaction txn, Map keys)
+ throws DbException {
+ for (Entry e : keys.entrySet()) {
+ TransportId t = e.getKey();
+ TransportKeyManager m = managers.get(t);
+ if (m == null) {
+ if (LOG.isLoggable(INFO)) LOG.info("No key manager for " + t);
+ } else {
+ m.activateKeys(txn, e.getValue());
+ }
+ }
+ }
+
@Override
public void removeKeys(Transaction txn, Map keys)
throws DbException {
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/MutableOutgoingKeys.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/MutableOutgoingKeys.java
index aaafec13b..c195f445c 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/transport/MutableOutgoingKeys.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/MutableOutgoingKeys.java
@@ -13,17 +13,19 @@ class MutableOutgoingKeys {
private final SecretKey tagKey, headerKey;
private final long rotationPeriod;
private long streamCounter;
+ private boolean active;
MutableOutgoingKeys(OutgoingKeys out) {
tagKey = out.getTagKey();
headerKey = out.getHeaderKey();
rotationPeriod = out.getRotationPeriod();
streamCounter = out.getStreamCounter();
+ active = out.isActive();
}
OutgoingKeys snapshot() {
return new OutgoingKeys(tagKey, headerKey, rotationPeriod,
- streamCounter);
+ streamCounter, active);
}
SecretKey getTagKey() {
@@ -45,4 +47,12 @@ class MutableOutgoingKeys {
void incrementStreamCounter() {
streamCounter++;
}
+
+ boolean isActive() {
+ return active;
+ }
+
+ void activate() {
+ active = true;
+ }
}
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManager.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManager.java
index 4eff0b289..2af01fa4a 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManager.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManager.java
@@ -23,6 +23,8 @@ interface TransportKeyManager {
void bindKeys(Transaction txn, ContactId c, KeySetId k) throws DbException;
+ void activateKeys(Transaction txn, KeySetId k) throws DbException;
+
void removeKeys(Transaction txn, KeySetId k) throws DbException;
void removeContact(ContactId c);
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java
index 889485d0d..d7ccb49c2 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java
@@ -127,10 +127,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
encodeTags(keySetId, contactId, m.getPreviousIncomingKeys());
encodeTags(keySetId, contactId, m.getCurrentIncomingKeys());
encodeTags(keySetId, contactId, m.getNextIncomingKeys());
- // Use the outgoing keys with the highest key set ID
- MutableKeySet old = outContexts.get(contactId);
- if (old == null || old.getKeySetId().getInt() < keySetId.getInt())
- outContexts.put(contactId, ks);
+ considerReplacingOutgoingKeys(ks);
}
}
@@ -147,6 +144,17 @@ class TransportKeyManagerImpl implements TransportKeyManager {
}
}
+ // Locking: lock
+ private void considerReplacingOutgoingKeys(MutableKeySet ks) {
+ // Use the active outgoing keys with the highest key set ID
+ if (ks.getTransportKeys().getCurrentOutgoingKeys().isActive()) {
+ MutableKeySet old = outContexts.get(ks.getContactId());
+ if (old == null ||
+ old.getKeySetId().getInt() < ks.getKeySetId().getInt())
+ outContexts.put(ks.getContactId(), ks);
+ }
+ }
+
private void scheduleKeyRotation(long now) {
long delay = rotationPeriodLength - now % rotationPeriodLength;
scheduler.schedule((Runnable) this::rotateKeys, delay, MILLISECONDS);
@@ -171,17 +179,17 @@ class TransportKeyManagerImpl implements TransportKeyManager {
@Override
public void addContact(Transaction txn, ContactId c, SecretKey master,
long timestamp, boolean alice) throws DbException {
- deriveAndAddKeys(txn, c, master, timestamp, alice);
+ deriveAndAddKeys(txn, c, master, timestamp, alice, true);
}
@Override
public KeySetId addUnboundKeys(Transaction txn, SecretKey master,
long timestamp, boolean alice) throws DbException {
- return deriveAndAddKeys(txn, null, master, timestamp, alice);
+ return deriveAndAddKeys(txn, null, master, timestamp, alice, false);
}
private KeySetId deriveAndAddKeys(Transaction txn, @Nullable ContactId c,
- SecretKey master, long timestamp, boolean alice)
+ SecretKey master, long timestamp, boolean alice, boolean active)
throws DbException {
lock.lock();
try {
@@ -189,7 +197,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
long rotationPeriod = timestamp / rotationPeriodLength;
// Derive the transport keys
TransportKeys k = transportCrypto.deriveTransportKeys(transportId,
- master, rotationPeriod, alice);
+ master, rotationPeriod, alice, active);
// Rotate the keys to the current rotation period if necessary
rotationPeriod = clock.currentTimeMillis() / rotationPeriodLength;
k = transportCrypto.rotateTransportKeys(k, rotationPeriod);
@@ -210,6 +218,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
try {
MutableKeySet ks = keys.get(k);
if (ks == null) throw new IllegalArgumentException();
+ // Check that the keys haven't already been bound
if (ks.getContactId() != null) throw new IllegalArgumentException();
MutableTransportKeys m = ks.getTransportKeys();
addKeys(k, c, m);
@@ -219,12 +228,30 @@ class TransportKeyManagerImpl implements TransportKeyManager {
}
}
+ @Override
+ public void activateKeys(Transaction txn, KeySetId k) throws DbException {
+ lock.lock();
+ try {
+ MutableKeySet ks = keys.get(k);
+ if (ks == null) throw new IllegalArgumentException();
+ // Check that the keys have been bound
+ if (ks.getContactId() == null) throw new IllegalArgumentException();
+ MutableTransportKeys m = ks.getTransportKeys();
+ m.getCurrentOutgoingKeys().activate();
+ considerReplacingOutgoingKeys(ks);
+ db.setTransportKeysActive(txn, m.getTransportId(), k);
+ } finally {
+ lock.unlock();
+ }
+ }
+
@Override
public void removeKeys(Transaction txn, KeySetId k) throws DbException {
lock.lock();
try {
MutableKeySet ks = keys.remove(k);
if (ks == null) throw new IllegalArgumentException();
+ // Check that the keys haven't been bound
if (ks.getContactId() != null) throw new IllegalArgumentException();
TransportId t = ks.getTransportKeys().getTransportId();
db.removeTransportKeys(txn, t, k);
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyDerivationTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyDerivationTest.java
index 81f73f8d2..dc51966ff 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyDerivationTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyDerivationTest.java
@@ -33,7 +33,7 @@ public class KeyDerivationTest extends BrambleTestCase {
@Test
public void testKeysAreDistinct() {
TransportKeys k = transportCrypto.deriveTransportKeys(transportId,
- master, 123, true);
+ master, 123, true, true);
assertAllDifferent(k);
}
@@ -41,9 +41,9 @@ public class KeyDerivationTest extends BrambleTestCase {
public void testCurrentKeysMatchCurrentKeysOfContact() {
// Start in rotation period 123
TransportKeys kA = transportCrypto.deriveTransportKeys(transportId,
- master, 123, true);
+ master, 123, true, true);
TransportKeys kB = transportCrypto.deriveTransportKeys(transportId,
- master, 123, false);
+ master, 123, false, true);
// Alice's incoming keys should equal Bob's outgoing keys
assertArrayEquals(kA.getCurrentIncomingKeys().getTagKey().getBytes(),
kB.getCurrentOutgoingKeys().getTagKey().getBytes());
@@ -73,9 +73,9 @@ public class KeyDerivationTest extends BrambleTestCase {
public void testPreviousKeysMatchPreviousKeysOfContact() {
// Start in rotation period 123
TransportKeys kA = transportCrypto.deriveTransportKeys(transportId,
- master, 123, true);
+ master, 123, true, true);
TransportKeys kB = transportCrypto.deriveTransportKeys(transportId,
- master, 123, false);
+ master, 123, false, true);
// Compare Alice's previous keys in period 456 with Bob's current keys
// in period 455
kA = transportCrypto.rotateTransportKeys(kA, 456);
@@ -100,9 +100,9 @@ public class KeyDerivationTest extends BrambleTestCase {
public void testNextKeysMatchNextKeysOfContact() {
// Start in rotation period 123
TransportKeys kA = transportCrypto.deriveTransportKeys(transportId,
- master, 123, true);
+ master, 123, true, true);
TransportKeys kB = transportCrypto.deriveTransportKeys(transportId,
- master, 123, false);
+ master, 123, false, true);
// Compare Alice's current keys in period 456 with Bob's next keys in
// period 455
kA = transportCrypto.rotateTransportKeys(kA, 456);
@@ -127,9 +127,9 @@ public class KeyDerivationTest extends BrambleTestCase {
SecretKey master1 = getSecretKey();
assertFalse(Arrays.equals(master.getBytes(), master1.getBytes()));
TransportKeys k = transportCrypto.deriveTransportKeys(transportId,
- master, 123, true);
+ master, 123, true, true);
TransportKeys k1 = transportCrypto.deriveTransportKeys(transportId,
- master1, 123, true);
+ master1, 123, true, true);
assertAllDifferent(k, k1);
}
@@ -138,9 +138,9 @@ public class KeyDerivationTest extends BrambleTestCase {
TransportId transportId1 = new TransportId("id1");
assertFalse(transportId.getString().equals(transportId1.getString()));
TransportKeys k = transportCrypto.deriveTransportKeys(transportId,
- master, 123, true);
+ master, 123, true, true);
TransportKeys k1 = transportCrypto.deriveTransportKeys(transportId1,
- master, 123, true);
+ master, 123, true, true);
assertAllDifferent(k, k1);
}
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java
index 61a499162..d8f1f59fb 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java
@@ -71,6 +71,7 @@ import static org.briarproject.bramble.api.transport.TransportConstants.REORDERI
import static org.briarproject.bramble.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
+import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -1356,22 +1357,22 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
}
private TransportKeys createTransportKeys() {
- SecretKey inPrevTagKey = TestUtils.getSecretKey();
- SecretKey inPrevHeaderKey = TestUtils.getSecretKey();
+ SecretKey inPrevTagKey = getSecretKey();
+ SecretKey inPrevHeaderKey = getSecretKey();
IncomingKeys inPrev = new IncomingKeys(inPrevTagKey, inPrevHeaderKey,
1, 123, new byte[4]);
- SecretKey inCurrTagKey = TestUtils.getSecretKey();
- SecretKey inCurrHeaderKey = TestUtils.getSecretKey();
+ SecretKey inCurrTagKey = getSecretKey();
+ SecretKey inCurrHeaderKey = getSecretKey();
IncomingKeys inCurr = new IncomingKeys(inCurrTagKey, inCurrHeaderKey,
2, 234, new byte[4]);
- SecretKey inNextTagKey = TestUtils.getSecretKey();
- SecretKey inNextHeaderKey = TestUtils.getSecretKey();
+ SecretKey inNextTagKey = getSecretKey();
+ SecretKey inNextHeaderKey = getSecretKey();
IncomingKeys inNext = new IncomingKeys(inNextTagKey, inNextHeaderKey,
3, 345, new byte[4]);
- SecretKey outCurrTagKey = TestUtils.getSecretKey();
- SecretKey outCurrHeaderKey = TestUtils.getSecretKey();
+ SecretKey outCurrTagKey = getSecretKey();
+ SecretKey outCurrHeaderKey = getSecretKey();
OutgoingKeys outCurr = new OutgoingKeys(outCurrTagKey, outCurrHeaderKey,
- 2, 456);
+ 2, 456, true);
return new TransportKeys(transportId, inPrev, inCurr, inNext, outCurr);
}
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java
index 6babc6459..9e4047982 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java
@@ -804,6 +804,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
actual.getHeaderKey().getBytes());
assertEquals(expected.getRotationPeriod(), actual.getRotationPeriod());
assertEquals(expected.getStreamCounter(), actual.getStreamCounter());
+ assertEquals(expected.isActive(), actual.isActive());
}
@Test
@@ -1820,7 +1821,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
SecretKey outCurrTagKey = getSecretKey();
SecretKey outCurrHeaderKey = getSecretKey();
OutgoingKeys outCurr = new OutgoingKeys(outCurrTagKey, outCurrHeaderKey,
- 2, 456);
+ 2, 456, true);
return new TransportKeys(transportId, inPrev, inCurr, inNext, outCurr);
}
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/transport/TransportKeyManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/transport/TransportKeyManagerImplTest.java
index afc5dfed2..8da8eefaa 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/transport/TransportKeyManagerImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/transport/TransportKeyManagerImplTest.java
@@ -65,16 +65,16 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
@Test
public void testKeysAreRotatedAtStartup() throws Exception {
- TransportKeys shouldRotate = createTransportKeys(900, 0);
- TransportKeys shouldNotRotate = createTransportKeys(1000, 0);
- TransportKeys shouldRotate1 = createTransportKeys(999, 0);
+ TransportKeys shouldRotate = createTransportKeys(900, 0, true);
+ TransportKeys shouldNotRotate = createTransportKeys(1000, 0, true);
+ TransportKeys shouldRotate1 = createTransportKeys(999, 0, false);
Collection loaded = asList(
new KeySet(keySetId, contactId, shouldRotate),
new KeySet(keySetId1, contactId1, shouldNotRotate),
new KeySet(keySetId2, null, shouldRotate1)
);
- TransportKeys rotated = createTransportKeys(1000, 0);
- TransportKeys rotated1 = createTransportKeys(1000, 0);
+ TransportKeys rotated = createTransportKeys(1000, 0, true);
+ TransportKeys rotated1 = createTransportKeys(1000, 0, false);
Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{
@@ -117,13 +117,13 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
@Test
public void testKeysAreRotatedWhenAddingContact() throws Exception {
boolean alice = random.nextBoolean();
- TransportKeys transportKeys = createTransportKeys(999, 0);
- TransportKeys rotated = createTransportKeys(1000, 0);
+ TransportKeys transportKeys = createTransportKeys(999, 0, true);
+ TransportKeys rotated = createTransportKeys(1000, 0, true);
Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{
oneOf(transportCrypto).deriveTransportKeys(transportId, masterKey,
- 999, alice);
+ 999, alice, true);
will(returnValue(transportKeys));
// Get the current time (1 ms after start of rotation period 1000)
oneOf(clock).currentTimeMillis();
@@ -155,13 +155,13 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
@Test
public void testKeysAreRotatedWhenAddingUnboundKeys() throws Exception {
boolean alice = random.nextBoolean();
- TransportKeys transportKeys = createTransportKeys(999, 0);
- TransportKeys rotated = createTransportKeys(1000, 0);
+ TransportKeys transportKeys = createTransportKeys(999, 0, false);
+ TransportKeys rotated = createTransportKeys(1000, 0, false);
Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{
oneOf(transportCrypto).deriveTransportKeys(transportId, masterKey,
- 999, alice);
+ 999, alice, false);
will(returnValue(transportKeys));
// Get the current time (1 ms after start of rotation period 1000)
oneOf(clock).currentTimeMillis();
@@ -200,7 +200,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
boolean alice = random.nextBoolean();
// The stream counter has been exhausted
TransportKeys transportKeys = createTransportKeys(1000,
- MAX_32_BIT_UNSIGNED + 1);
+ MAX_32_BIT_UNSIGNED + 1, true);
Transaction txn = new Transaction(null, false);
expectAddContactNoRotation(alice, transportKeys, txn);
@@ -220,7 +220,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
boolean alice = random.nextBoolean();
// The stream counter can be used one more time before being exhausted
TransportKeys transportKeys = createTransportKeys(1000,
- MAX_32_BIT_UNSIGNED);
+ MAX_32_BIT_UNSIGNED, true);
Transaction txn = new Transaction(null, false);
expectAddContactNoRotation(alice, transportKeys, txn);
@@ -254,7 +254,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
public void testIncomingStreamContextIsNullIfTagIsNotFound()
throws Exception {
boolean alice = random.nextBoolean();
- TransportKeys transportKeys = createTransportKeys(1000, 0);
+ TransportKeys transportKeys = createTransportKeys(1000, 0, true);
Transaction txn = new Transaction(null, false);
expectAddContactNoRotation(alice, transportKeys, txn);
@@ -274,14 +274,14 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
@Test
public void testTagIsNotRecognisedTwice() throws Exception {
boolean alice = random.nextBoolean();
- TransportKeys transportKeys = createTransportKeys(1000, 0);
+ TransportKeys transportKeys = createTransportKeys(1000, 0, true);
// Keep a copy of the tags
List tags = new ArrayList<>();
Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{
oneOf(transportCrypto).deriveTransportKeys(transportId, masterKey,
- 1000, alice);
+ 1000, alice, true);
will(returnValue(transportKeys));
// Get the current time (the start of rotation period 1000)
oneOf(clock).currentTimeMillis();
@@ -335,14 +335,14 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
@Test
public void testKeysAreRotatedToCurrentPeriod() throws Exception {
- TransportKeys transportKeys = createTransportKeys(1000, 0);
- TransportKeys transportKeys1 = createTransportKeys(1000, 0);
+ TransportKeys transportKeys = createTransportKeys(1000, 0, true);
+ TransportKeys transportKeys1 = createTransportKeys(1000, 0, false);
Collection loaded = asList(
new KeySet(keySetId, contactId, transportKeys),
new KeySet(keySetId1, null, transportKeys1)
);
- TransportKeys rotated = createTransportKeys(1001, 0);
- TransportKeys rotated1 = createTransportKeys(1001, 0);
+ TransportKeys rotated = createTransportKeys(1001, 0, true);
+ TransportKeys rotated1 = createTransportKeys(1001, 0, false);
Transaction txn = new Transaction(null, false);
Transaction txn1 = new Transaction(null, false);
@@ -411,14 +411,14 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
}
@Test
- public void testTagsAreEncodedWhenKeysAreBound() throws Exception {
+ public void testBindingAndActivatingKeys() throws Exception {
boolean alice = random.nextBoolean();
- TransportKeys transportKeys = createTransportKeys(1000, 0);
+ TransportKeys transportKeys = createTransportKeys(1000, 0, false);
Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{
oneOf(transportCrypto).deriveTransportKeys(transportId, masterKey,
- 1000, alice);
+ 1000, alice, false);
will(returnValue(transportKeys));
// Get the current time (the start of rotation period 1000)
oneOf(clock).currentTimeMillis();
@@ -438,6 +438,10 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
}
// Save the key binding
oneOf(db).bindTransportKeys(txn, contactId, transportId, keySetId);
+ // Activate the keys
+ oneOf(db).setTransportKeysActive(txn, transportId, keySetId);
+ // Increment the stream counter
+ oneOf(db).incrementStreamCounter(txn, contactId, transportId, 1000);
}});
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
@@ -448,17 +452,29 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
assertEquals(keySetId, transportKeyManager.addUnboundKeys(txn,
masterKey, timestamp, alice));
transportKeyManager.bindKeys(txn, contactId, keySetId);
+ // The keys are inactive so no stream context should be returned
+ assertNull(transportKeyManager.getStreamContext(txn, contactId));
+ transportKeyManager.activateKeys(txn, keySetId);
+ // The keys are active so a stream context should be returned
+ StreamContext ctx = transportKeyManager.getStreamContext(txn,
+ contactId);
+ assertNotNull(ctx);
+ assertEquals(contactId, ctx.getContactId());
+ assertEquals(transportId, ctx.getTransportId());
+ assertEquals(tagKey, ctx.getTagKey());
+ assertEquals(headerKey, ctx.getHeaderKey());
+ assertEquals(0, ctx.getStreamNumber());
}
@Test
public void testRemovingUnboundKeys() throws Exception {
boolean alice = random.nextBoolean();
- TransportKeys transportKeys = createTransportKeys(1000, 0);
+ TransportKeys transportKeys = createTransportKeys(1000, 0, false);
Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{
oneOf(transportCrypto).deriveTransportKeys(transportId, masterKey,
- 1000, alice);
+ 1000, alice, false);
will(returnValue(transportKeys));
// Get the current time (the start of rotation period 1000)
oneOf(clock).currentTimeMillis();
@@ -487,7 +503,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
TransportKeys transportKeys, Transaction txn) throws Exception {
context.checking(new Expectations() {{
oneOf(transportCrypto).deriveTransportKeys(transportId, masterKey,
- 1000, alice);
+ 1000, alice, true);
will(returnValue(transportKeys));
// Get the current time (the start of rotation period 1000)
oneOf(clock).currentTimeMillis();
@@ -509,7 +525,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
}
private TransportKeys createTransportKeys(long rotationPeriod,
- long streamCounter) {
+ long streamCounter, boolean active) {
IncomingKeys inPrev = new IncomingKeys(tagKey, headerKey,
rotationPeriod - 1);
IncomingKeys inCurr = new IncomingKeys(tagKey, headerKey,
@@ -517,7 +533,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
IncomingKeys inNext = new IncomingKeys(tagKey, headerKey,
rotationPeriod + 1);
OutgoingKeys outCurr = new OutgoingKeys(tagKey, headerKey,
- rotationPeriod, streamCounter);
+ rotationPeriod, streamCounter, active);
return new TransportKeys(transportId, inPrev, inCurr, inNext, outCurr);
}