mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 13:19:52 +01:00
Remove support for unbound transport keys.
This commit is contained in:
@@ -45,9 +45,9 @@ public interface ContactManager {
|
|||||||
*
|
*
|
||||||
* @param alice true if the local party is Alice
|
* @param alice true if the local party is Alice
|
||||||
*/
|
*/
|
||||||
ContactId addContact(Author remote, AuthorId local,
|
ContactId addContact(Author remote, AuthorId local, SecretKey master,
|
||||||
SecretKey master, long timestamp, boolean alice, boolean verified,
|
long timestamp, boolean alice, boolean verified, boolean active)
|
||||||
boolean active) throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the contact with the given ID.
|
* Returns the contact with the given ID.
|
||||||
|
|||||||
@@ -104,18 +104,12 @@ public interface DatabaseComponent {
|
|||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the given transport keys, optionally binding them to the given
|
* Stores the given transport keys for the given contact and returns a
|
||||||
* contact, and returns a key set ID.
|
* key set ID.
|
||||||
*/
|
*/
|
||||||
KeySetId addTransportKeys(Transaction txn, @Nullable ContactId c,
|
KeySetId addTransportKeys(Transaction txn, ContactId c,
|
||||||
TransportKeys k) throws DbException;
|
TransportKeys k) throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds the given keys for the given transport to the given contact.
|
|
||||||
*/
|
|
||||||
void bindTransportKeys(Transaction txn, ContactId c, TransportId t,
|
|
||||||
KeySetId k) throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the database contains the given contact for the given
|
* Returns true if the database contains the given contact for the given
|
||||||
* local pseudonym.
|
* local pseudonym.
|
||||||
|
|||||||
@@ -19,48 +19,24 @@ public interface KeyManager {
|
|||||||
/**
|
/**
|
||||||
* Informs the key manager that a new contact has been added. Derives and
|
* Informs the key manager that a new contact has been added. Derives and
|
||||||
* stores a set of transport keys for communicating with the contact over
|
* stores a set of transport keys for communicating with the contact over
|
||||||
* each transport.
|
* each transport and returns the key set IDs.
|
||||||
* <p/>
|
* <p/>
|
||||||
* {@link StreamContext StreamContexts} for the contact can be created
|
* {@link StreamContext StreamContexts} for the contact can be created
|
||||||
* after this method has returned.
|
* after this method has returned.
|
||||||
*
|
*
|
||||||
* @param alice true if the local party is Alice
|
* @param alice true if the local party is Alice
|
||||||
|
* @param active whether the derived keys can be used for outgoing streams
|
||||||
*/
|
*/
|
||||||
void addContact(Transaction txn, ContactId c, SecretKey master,
|
Map<TransportId, KeySetId> addContact(Transaction txn, ContactId c,
|
||||||
long timestamp, boolean alice) throws DbException;
|
SecretKey master, long timestamp, boolean alice, boolean active)
|
||||||
|
|
||||||
/**
|
|
||||||
* Derives and stores a set of unbound transport keys for each transport
|
|
||||||
* and returns the key set IDs.
|
|
||||||
* <p/>
|
|
||||||
* The keys must be bound before they can be used for incoming streams,
|
|
||||||
* and also activated before they can be used for outgoing streams.
|
|
||||||
*
|
|
||||||
* @param alice true if the local party is Alice
|
|
||||||
*/
|
|
||||||
Map<TransportId, KeySetId> addUnboundKeys(Transaction txn, SecretKey master,
|
|
||||||
long timestamp, boolean alice) throws DbException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds the given transport keys to the given contact.
|
|
||||||
*/
|
|
||||||
void bindKeys(Transaction txn, ContactId c, Map<TransportId, KeySetId> keys)
|
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the given transport keys as usable for outgoing streams. Keys must
|
* Marks the given transport keys as usable for outgoing streams.
|
||||||
* be bound before they are activated.
|
|
||||||
*/
|
*/
|
||||||
void activateKeys(Transaction txn, Map<TransportId, KeySetId> keys)
|
void activateKeys(Transaction txn, Map<TransportId, KeySetId> keys)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the given transport keys, which must not have been bound, from
|
|
||||||
* the manager and the database.
|
|
||||||
*/
|
|
||||||
void removeKeys(Transaction txn, Map<TransportId, KeySetId> keys)
|
|
||||||
throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if we have keys that can be used for outgoing streams to
|
* Returns true if we have keys that can be used for outgoing streams to
|
||||||
* the given contact over the given transport.
|
* the given contact over the given transport.
|
||||||
|
|||||||
@@ -3,23 +3,20 @@ package org.briarproject.bramble.api.transport;
|
|||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A set of transport keys for communicating with a contact. If the keys have
|
* A set of transport keys for communicating with a contact.
|
||||||
* not yet been bound to a contact, {@link #getContactId()}} returns null.
|
|
||||||
*/
|
*/
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class KeySet {
|
public class KeySet {
|
||||||
|
|
||||||
private final KeySetId keySetId;
|
private final KeySetId keySetId;
|
||||||
@Nullable
|
|
||||||
private final ContactId contactId;
|
private final ContactId contactId;
|
||||||
private final TransportKeys transportKeys;
|
private final TransportKeys transportKeys;
|
||||||
|
|
||||||
public KeySet(KeySetId keySetId, @Nullable ContactId contactId,
|
public KeySet(KeySetId keySetId, ContactId contactId,
|
||||||
TransportKeys transportKeys) {
|
TransportKeys transportKeys) {
|
||||||
this.keySetId = keySetId;
|
this.keySetId = keySetId;
|
||||||
this.contactId = contactId;
|
this.contactId = contactId;
|
||||||
@@ -30,7 +27,6 @@ public class KeySet {
|
|||||||
return keySetId;
|
return keySetId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public ContactId getContactId() {
|
public ContactId getContactId() {
|
||||||
return contactId;
|
return contactId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class ContactManagerImpl implements ContactManager {
|
|||||||
SecretKey master, long timestamp, boolean alice, boolean verified,
|
SecretKey master, long timestamp, boolean alice, boolean verified,
|
||||||
boolean active) throws DbException {
|
boolean active) throws DbException {
|
||||||
ContactId c = db.addContact(txn, remote, local, verified, active);
|
ContactId c = db.addContact(txn, remote, local, verified, active);
|
||||||
keyManager.addContact(txn, c, master, timestamp, alice);
|
keyManager.addContact(txn, c, master, timestamp, alice, active);
|
||||||
Contact contact = db.getContact(txn, c);
|
Contact contact = db.getContact(txn, c);
|
||||||
for (ContactHook hook : hooks) hook.addingContact(txn, contact);
|
for (ContactHook hook : hooks) hook.addingContact(txn, contact);
|
||||||
return c;
|
return c;
|
||||||
|
|||||||
@@ -125,16 +125,10 @@ interface Database<T> {
|
|||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the given transport keys, optionally binding them to the given
|
* Stores the given transport keys for the given contact and returns a
|
||||||
* contact, and returns a key set ID.
|
* key set ID.
|
||||||
*/
|
*/
|
||||||
KeySetId addTransportKeys(T txn, @Nullable ContactId c, TransportKeys k)
|
KeySetId addTransportKeys(T txn, ContactId c, TransportKeys k)
|
||||||
throws DbException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds the given keys for the given transport to the given contact.
|
|
||||||
*/
|
|
||||||
void bindTransportKeys(T txn, ContactId c, TransportId t, KeySetId k)
|
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -234,27 +234,15 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeySetId addTransportKeys(Transaction transaction,
|
public KeySetId addTransportKeys(Transaction transaction, ContactId c,
|
||||||
@Nullable ContactId c, TransportKeys k) throws DbException {
|
TransportKeys k) throws DbException {
|
||||||
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
|
||||||
T txn = unbox(transaction);
|
|
||||||
if (c != null && !db.containsContact(txn, c))
|
|
||||||
throw new NoSuchContactException();
|
|
||||||
if (!db.containsTransport(txn, k.getTransportId()))
|
|
||||||
throw new NoSuchTransportException();
|
|
||||||
return db.addTransportKeys(txn, c, k);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bindTransportKeys(Transaction transaction, ContactId c,
|
|
||||||
TransportId t, KeySetId k) throws DbException {
|
|
||||||
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
||||||
T txn = unbox(transaction);
|
T txn = unbox(transaction);
|
||||||
if (!db.containsContact(txn, c))
|
if (!db.containsContact(txn, c))
|
||||||
throw new NoSuchContactException();
|
throw new NoSuchContactException();
|
||||||
if (!db.containsTransport(txn, t))
|
if (!db.containsTransport(txn, k.getTransportId()))
|
||||||
throw new NoSuchTransportException();
|
throw new NoSuchTransportException();
|
||||||
db.bindTransportKeys(txn, c, t, k);
|
return db.addTransportKeys(txn, c, k);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " (transportId _STRING NOT NULL,"
|
+ " (transportId _STRING NOT NULL,"
|
||||||
+ " keySetId _COUNTER,"
|
+ " keySetId _COUNTER,"
|
||||||
+ " rotationPeriod BIGINT NOT NULL,"
|
+ " rotationPeriod BIGINT NOT NULL,"
|
||||||
+ " contactId INT," // Null if keys are not bound
|
+ " contactId INT NOT NULL,"
|
||||||
+ " tagKey _SECRET NOT NULL,"
|
+ " tagKey _SECRET NOT NULL,"
|
||||||
+ " headerKey _SECRET NOT NULL,"
|
+ " headerKey _SECRET NOT NULL,"
|
||||||
+ " stream BIGINT NOT NULL,"
|
+ " stream BIGINT NOT NULL,"
|
||||||
@@ -255,7 +255,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " (transportId _STRING NOT NULL,"
|
+ " (transportId _STRING NOT NULL,"
|
||||||
+ " keySetId INT NOT NULL,"
|
+ " keySetId INT NOT NULL,"
|
||||||
+ " rotationPeriod BIGINT NOT NULL,"
|
+ " rotationPeriod BIGINT NOT NULL,"
|
||||||
+ " contactId INT," // Null if keys are not bound
|
+ " contactId INT NOT NULL,"
|
||||||
+ " tagKey _SECRET NOT NULL,"
|
+ " tagKey _SECRET NOT NULL,"
|
||||||
+ " headerKey _SECRET NOT NULL,"
|
+ " headerKey _SECRET NOT NULL,"
|
||||||
+ " base BIGINT NOT NULL,"
|
+ " base BIGINT NOT NULL,"
|
||||||
@@ -883,7 +883,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeySetId addTransportKeys(Connection txn, @Nullable ContactId c,
|
public KeySetId addTransportKeys(Connection txn, ContactId c,
|
||||||
TransportKeys k) throws DbException {
|
TransportKeys k) throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
@@ -893,8 +893,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " rotationPeriod, tagKey, headerKey, stream, active)"
|
+ " rotationPeriod, tagKey, headerKey, stream, active)"
|
||||||
+ " VALUES (?, ?, ?, ?, ?, ?, ?)";
|
+ " VALUES (?, ?, ?, ?, ?, ?, ?)";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
if (c == null) ps.setNull(1, INTEGER);
|
ps.setInt(1, c.getInt());
|
||||||
else ps.setInt(1, c.getInt());
|
|
||||||
ps.setString(2, k.getTransportId().getString());
|
ps.setString(2, k.getTransportId().getString());
|
||||||
OutgoingKeys outCurr = k.getCurrentOutgoingKeys();
|
OutgoingKeys outCurr = k.getCurrentOutgoingKeys();
|
||||||
ps.setLong(3, outCurr.getRotationPeriod());
|
ps.setLong(3, outCurr.getRotationPeriod());
|
||||||
@@ -922,8 +921,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setInt(1, keySetId.getInt());
|
ps.setInt(1, keySetId.getInt());
|
||||||
if (c == null) ps.setNull(2, INTEGER);
|
ps.setInt(2, c.getInt());
|
||||||
else ps.setInt(2, c.getInt());
|
|
||||||
ps.setString(3, k.getTransportId().getString());
|
ps.setString(3, k.getTransportId().getString());
|
||||||
// Previous rotation period
|
// Previous rotation period
|
||||||
IncomingKeys inPrev = k.getPreviousIncomingKeys();
|
IncomingKeys inPrev = k.getPreviousIncomingKeys();
|
||||||
@@ -965,33 +963,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bindTransportKeys(Connection txn, ContactId c, TransportId t,
|
|
||||||
KeySetId k) throws DbException {
|
|
||||||
PreparedStatement ps = null;
|
|
||||||
try {
|
|
||||||
String sql = "UPDATE outgoingKeys SET contactId = ?"
|
|
||||||
+ " WHERE keySetId = ?";
|
|
||||||
ps = txn.prepareStatement(sql);
|
|
||||||
ps.setInt(1, c.getInt());
|
|
||||||
ps.setInt(2, k.getInt());
|
|
||||||
int affected = ps.executeUpdate();
|
|
||||||
if (affected < 0) throw new DbStateException();
|
|
||||||
ps.close();
|
|
||||||
sql = "UPDATE incomingKeys SET contactId = ?"
|
|
||||||
+ " WHERE keySetId = ?";
|
|
||||||
ps = txn.prepareStatement(sql);
|
|
||||||
ps.setInt(1, c.getInt());
|
|
||||||
ps.setInt(2, k.getInt());
|
|
||||||
affected = ps.executeUpdate();
|
|
||||||
if (affected < 0) throw new DbStateException();
|
|
||||||
ps.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
tryToClose(ps);
|
|
||||||
throw new DbException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsContact(Connection txn, AuthorId remote,
|
public boolean containsContact(Connection txn, AuthorId remote,
|
||||||
AuthorId local) throws DbException {
|
AuthorId local) throws DbException {
|
||||||
@@ -2172,7 +2143,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
if (inKeys.size() < (i + 1) * 3) throw new DbStateException();
|
if (inKeys.size() < (i + 1) * 3) throw new DbStateException();
|
||||||
KeySetId keySetId = new KeySetId(rs.getInt(1));
|
KeySetId keySetId = new KeySetId(rs.getInt(1));
|
||||||
ContactId contactId = new ContactId(rs.getInt(2));
|
ContactId contactId = new ContactId(rs.getInt(2));
|
||||||
if (rs.wasNull()) contactId = null;
|
|
||||||
long rotationPeriod = rs.getLong(3);
|
long rotationPeriod = rs.getLong(3);
|
||||||
SecretKey tagKey = new SecretKey(rs.getBytes(4));
|
SecretKey tagKey = new SecretKey(rs.getBytes(4));
|
||||||
SecretKey headerKey = new SecretKey(rs.getBytes(5));
|
SecretKey headerKey = new SecretKey(rs.getBytes(5));
|
||||||
|
|||||||
@@ -99,39 +99,18 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addContact(Transaction txn, ContactId c, SecretKey master,
|
public Map<TransportId, KeySetId> addContact(Transaction txn, ContactId c,
|
||||||
long timestamp, boolean alice) throws DbException {
|
SecretKey master, long timestamp, boolean alice, boolean active)
|
||||||
for (TransportKeyManager m : managers.values())
|
|
||||||
m.addContact(txn, c, master, timestamp, alice);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<TransportId, KeySetId> addUnboundKeys(Transaction txn,
|
|
||||||
SecretKey master, long timestamp, boolean alice)
|
|
||||||
throws DbException {
|
throws DbException {
|
||||||
Map<TransportId, KeySetId> ids = new HashMap<>();
|
Map<TransportId, KeySetId> ids = new HashMap<>();
|
||||||
for (Entry<TransportId, TransportKeyManager> e : managers.entrySet()) {
|
for (Entry<TransportId, TransportKeyManager> e : managers.entrySet()) {
|
||||||
TransportId t = e.getKey();
|
TransportId t = e.getKey();
|
||||||
TransportKeyManager m = e.getValue();
|
TransportKeyManager m = e.getValue();
|
||||||
ids.put(t, m.addUnboundKeys(txn, master, timestamp, alice));
|
ids.put(t, m.addContact(txn, c, master, timestamp, alice, active));
|
||||||
}
|
}
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bindKeys(Transaction txn, ContactId c,
|
|
||||||
Map<TransportId, KeySetId> keys) throws DbException {
|
|
||||||
for (Entry<TransportId, KeySetId> 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.bindKeys(txn, c, e.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void activateKeys(Transaction txn, Map<TransportId, KeySetId> keys)
|
public void activateKeys(Transaction txn, Map<TransportId, KeySetId> keys)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
@@ -146,24 +125,10 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeKeys(Transaction txn, Map<TransportId, KeySetId> keys)
|
|
||||||
throws DbException {
|
|
||||||
for (Entry<TransportId, KeySetId> 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.removeKeys(txn, e.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canSendOutgoingStreams(ContactId c, TransportId t) {
|
public boolean canSendOutgoingStreams(ContactId c, TransportId t) {
|
||||||
TransportKeyManager m = managers.get(t);
|
TransportKeyManager m = managers.get(t);
|
||||||
return m == null ? false : m.canSendOutgoingStreams(c);
|
return m != null && m.canSendOutgoingStreams(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -3,32 +3,28 @@ package org.briarproject.bramble.transport;
|
|||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
import org.briarproject.bramble.api.transport.KeySetId;
|
import org.briarproject.bramble.api.transport.KeySetId;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
class MutableKeySet {
|
||||||
|
|
||||||
public class MutableKeySet {
|
|
||||||
|
|
||||||
private final KeySetId keySetId;
|
private final KeySetId keySetId;
|
||||||
@Nullable
|
|
||||||
private final ContactId contactId;
|
private final ContactId contactId;
|
||||||
private final MutableTransportKeys transportKeys;
|
private final MutableTransportKeys transportKeys;
|
||||||
|
|
||||||
public MutableKeySet(KeySetId keySetId, @Nullable ContactId contactId,
|
MutableKeySet(KeySetId keySetId, ContactId contactId,
|
||||||
MutableTransportKeys transportKeys) {
|
MutableTransportKeys transportKeys) {
|
||||||
this.keySetId = keySetId;
|
this.keySetId = keySetId;
|
||||||
this.contactId = contactId;
|
this.contactId = contactId;
|
||||||
this.transportKeys = transportKeys;
|
this.transportKeys = transportKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeySetId getKeySetId() {
|
KeySetId getKeySetId() {
|
||||||
return keySetId;
|
return keySetId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
ContactId getContactId() {
|
||||||
public ContactId getContactId() {
|
|
||||||
return contactId;
|
return contactId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutableTransportKeys getTransportKeys() {
|
MutableTransportKeys getTransportKeys() {
|
||||||
return transportKeys;
|
return transportKeys;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,18 +15,11 @@ interface TransportKeyManager {
|
|||||||
|
|
||||||
void start(Transaction txn) throws DbException;
|
void start(Transaction txn) throws DbException;
|
||||||
|
|
||||||
void addContact(Transaction txn, ContactId c, SecretKey master,
|
KeySetId addContact(Transaction txn, ContactId c, SecretKey master,
|
||||||
long timestamp, boolean alice) throws DbException;
|
long timestamp, boolean alice, boolean active) throws DbException;
|
||||||
|
|
||||||
KeySetId addUnboundKeys(Transaction txn, SecretKey master, long timestamp,
|
|
||||||
boolean alice) throws DbException;
|
|
||||||
|
|
||||||
void bindKeys(Transaction txn, ContactId c, KeySetId k) throws DbException;
|
|
||||||
|
|
||||||
void activateKeys(Transaction txn, KeySetId k) throws DbException;
|
void activateKeys(Transaction txn, KeySetId k) throws DbException;
|
||||||
|
|
||||||
void removeKeys(Transaction txn, KeySetId k) throws DbException;
|
|
||||||
|
|
||||||
void removeContact(ContactId c);
|
void removeContact(ContactId c);
|
||||||
|
|
||||||
boolean canSendOutgoingStreams(ContactId c);
|
boolean canSendOutgoingStreams(ContactId c);
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.annotation.concurrent.ThreadSafe;
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
|
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
@@ -119,16 +118,14 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Locking: lock
|
// Locking: lock
|
||||||
private void addKeys(KeySetId keySetId, @Nullable ContactId contactId,
|
private void addKeys(KeySetId keySetId, ContactId contactId,
|
||||||
MutableTransportKeys m) {
|
MutableTransportKeys m) {
|
||||||
MutableKeySet ks = new MutableKeySet(keySetId, contactId, m);
|
MutableKeySet ks = new MutableKeySet(keySetId, contactId, m);
|
||||||
keys.put(keySetId, ks);
|
keys.put(keySetId, ks);
|
||||||
if (contactId != null) {
|
encodeTags(keySetId, contactId, m.getPreviousIncomingKeys());
|
||||||
encodeTags(keySetId, contactId, m.getPreviousIncomingKeys());
|
encodeTags(keySetId, contactId, m.getCurrentIncomingKeys());
|
||||||
encodeTags(keySetId, contactId, m.getCurrentIncomingKeys());
|
encodeTags(keySetId, contactId, m.getNextIncomingKeys());
|
||||||
encodeTags(keySetId, contactId, m.getNextIncomingKeys());
|
considerReplacingOutgoingKeys(ks);
|
||||||
considerReplacingOutgoingKeys(ks);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Locking: lock
|
// Locking: lock
|
||||||
@@ -150,8 +147,9 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
if (ks.getTransportKeys().getCurrentOutgoingKeys().isActive()) {
|
if (ks.getTransportKeys().getCurrentOutgoingKeys().isActive()) {
|
||||||
MutableKeySet old = outContexts.get(ks.getContactId());
|
MutableKeySet old = outContexts.get(ks.getContactId());
|
||||||
if (old == null ||
|
if (old == null ||
|
||||||
old.getKeySetId().getInt() < ks.getKeySetId().getInt())
|
old.getKeySetId().getInt() < ks.getKeySetId().getInt()) {
|
||||||
outContexts.put(ks.getContactId(), ks);
|
outContexts.put(ks.getContactId(), ks);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,20 +175,8 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addContact(Transaction txn, ContactId c, SecretKey master,
|
public KeySetId addContact(Transaction txn, ContactId c, SecretKey master,
|
||||||
long timestamp, boolean alice) throws DbException {
|
long timestamp, boolean alice, boolean active) throws DbException {
|
||||||
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, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private KeySetId deriveAndAddKeys(Transaction txn, @Nullable ContactId c,
|
|
||||||
SecretKey master, long timestamp, boolean alice, boolean active)
|
|
||||||
throws DbException {
|
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
// Work out what rotation period the timestamp belongs to
|
// Work out what rotation period the timestamp belongs to
|
||||||
@@ -211,31 +197,12 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bindKeys(Transaction txn, ContactId c, KeySetId k)
|
|
||||||
throws DbException {
|
|
||||||
lock.lock();
|
|
||||||
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);
|
|
||||||
db.bindTransportKeys(txn, c, m.getTransportId(), k);
|
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void activateKeys(Transaction txn, KeySetId k) throws DbException {
|
public void activateKeys(Transaction txn, KeySetId k) throws DbException {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
MutableKeySet ks = keys.get(k);
|
MutableKeySet ks = keys.get(k);
|
||||||
if (ks == null) throw new IllegalArgumentException();
|
if (ks == null) throw new IllegalArgumentException();
|
||||||
// Check that the keys have been bound
|
|
||||||
if (ks.getContactId() == null) throw new IllegalArgumentException();
|
|
||||||
MutableTransportKeys m = ks.getTransportKeys();
|
MutableTransportKeys m = ks.getTransportKeys();
|
||||||
m.getCurrentOutgoingKeys().activate();
|
m.getCurrentOutgoingKeys().activate();
|
||||||
considerReplacingOutgoingKeys(ks);
|
considerReplacingOutgoingKeys(ks);
|
||||||
@@ -245,21 +212,6 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@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);
|
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeContact(ContactId c) {
|
public void removeContact(ContactId c) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
oneOf(db).addContact(txn, remote, local, verified, active);
|
oneOf(db).addContact(txn, remote, local, verified, active);
|
||||||
will(returnValue(contactId));
|
will(returnValue(contactId));
|
||||||
oneOf(keyManager)
|
oneOf(keyManager).addContact(txn, contactId, master, timestamp,
|
||||||
.addContact(txn, contactId, master, timestamp, alice);
|
alice, active);
|
||||||
oneOf(db).getContact(txn, contactId);
|
oneOf(db).getContact(txn, contactId);
|
||||||
will(returnValue(contact));
|
will(returnValue(contact));
|
||||||
oneOf(db).commitTransaction(txn);
|
oneOf(db).commitTransaction(txn);
|
||||||
|
|||||||
@@ -289,11 +289,11 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Check whether the contact is in the DB (which it's not)
|
// Check whether the contact is in the DB (which it's not)
|
||||||
exactly(17).of(database).startTransaction();
|
exactly(16).of(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
exactly(17).of(database).containsContact(txn, contactId);
|
exactly(16).of(database).containsContact(txn, contactId);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
exactly(17).of(database).abortTransaction(txn);
|
exactly(16).of(database).abortTransaction(txn);
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
||||||
shutdown);
|
shutdown);
|
||||||
@@ -308,16 +308,6 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
|
|||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction = db.startTransaction(false);
|
|
||||||
try {
|
|
||||||
db.bindTransportKeys(transaction, contactId, transportId, keySetId);
|
|
||||||
fail();
|
|
||||||
} catch (NoSuchContactException expected) {
|
|
||||||
// Expected
|
|
||||||
} finally {
|
|
||||||
db.endTransaction(transaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
transaction = db.startTransaction(false);
|
transaction = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
db.generateAck(transaction, contactId, 123);
|
db.generateAck(transaction, contactId, 123);
|
||||||
@@ -773,13 +763,11 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
|
|||||||
// endTransaction()
|
// endTransaction()
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
// Check whether the transport is in the DB (which it's not)
|
// Check whether the transport is in the DB (which it's not)
|
||||||
exactly(6).of(database).startTransaction();
|
exactly(5).of(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
oneOf(database).containsContact(txn, contactId);
|
exactly(5).of(database).containsTransport(txn, transportId);
|
||||||
will(returnValue(true));
|
|
||||||
exactly(6).of(database).containsTransport(txn, transportId);
|
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
exactly(6).of(database).abortTransaction(txn);
|
exactly(5).of(database).abortTransaction(txn);
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
||||||
shutdown);
|
shutdown);
|
||||||
@@ -794,16 +782,6 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
|
|||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction = db.startTransaction(false);
|
|
||||||
try {
|
|
||||||
db.bindTransportKeys(transaction, contactId, transportId, keySetId);
|
|
||||||
fail();
|
|
||||||
} catch (NoSuchTransportException expected) {
|
|
||||||
// Expected
|
|
||||||
} finally {
|
|
||||||
db.endTransaction(transaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
transaction = db.startTransaction(false);
|
transaction = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
db.getTransportKeys(transaction, transportId);
|
db.getTransportKeys(transaction, transportId);
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
private final TransportId transportId;
|
private final TransportId transportId;
|
||||||
private final ContactId contactId;
|
private final ContactId contactId;
|
||||||
private final KeySetId keySetId, keySetId1;
|
private final KeySetId keySetId, keySetId1;
|
||||||
|
private final Random random = new Random();
|
||||||
|
|
||||||
JdbcDatabaseTest() throws Exception {
|
JdbcDatabaseTest() throws Exception {
|
||||||
clientId = getClientId();
|
clientId = getClientId();
|
||||||
@@ -670,8 +671,9 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testTransportKeys() throws Exception {
|
public void testTransportKeys() throws Exception {
|
||||||
long rotationPeriod = 123, rotationPeriod1 = 234;
|
long rotationPeriod = 123, rotationPeriod1 = 234;
|
||||||
TransportKeys keys = createTransportKeys(rotationPeriod);
|
boolean active = random.nextBoolean();
|
||||||
TransportKeys keys1 = createTransportKeys(rotationPeriod1);
|
TransportKeys keys = createTransportKeys(rotationPeriod, active);
|
||||||
|
TransportKeys keys1 = createTransportKeys(rotationPeriod1, active);
|
||||||
|
|
||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
@@ -682,7 +684,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
// Add the contact, the transport and the transport keys
|
// Add the contact, the transport and the transport keys
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
db.addLocalAuthor(txn, localAuthor);
|
||||||
assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
|
assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
|
||||||
true, true));
|
true, active));
|
||||||
db.addTransport(txn, transportId, 123);
|
db.addTransport(txn, transportId, 123);
|
||||||
assertEquals(keySetId, db.addTransportKeys(txn, contactId, keys));
|
assertEquals(keySetId, db.addTransportKeys(txn, contactId, keys));
|
||||||
assertEquals(keySetId1, db.addTransportKeys(txn, contactId, keys1));
|
assertEquals(keySetId1, db.addTransportKeys(txn, contactId, keys1));
|
||||||
@@ -701,8 +703,9 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rotate the transport keys
|
// Rotate the transport keys
|
||||||
TransportKeys rotated = createTransportKeys(rotationPeriod + 1);
|
TransportKeys rotated = createTransportKeys(rotationPeriod + 1, active);
|
||||||
TransportKeys rotated1 = createTransportKeys(rotationPeriod1 + 1);
|
TransportKeys rotated1 =
|
||||||
|
createTransportKeys(rotationPeriod1 + 1, active);
|
||||||
db.updateTransportKeys(txn, new KeySet(keySetId, contactId, rotated));
|
db.updateTransportKeys(txn, new KeySet(keySetId, contactId, rotated));
|
||||||
db.updateTransportKeys(txn, new KeySet(keySetId1, contactId, rotated1));
|
db.updateTransportKeys(txn, new KeySet(keySetId1, contactId, rotated1));
|
||||||
|
|
||||||
@@ -727,95 +730,6 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUnboundTransportKeys() throws Exception {
|
|
||||||
long rotationPeriod = 123, rotationPeriod1 = 234;
|
|
||||||
TransportKeys keys = createTransportKeys(rotationPeriod);
|
|
||||||
TransportKeys keys1 = createTransportKeys(rotationPeriod1);
|
|
||||||
|
|
||||||
Database<Connection> db = open(false);
|
|
||||||
Connection txn = db.startTransaction();
|
|
||||||
|
|
||||||
// Initially there should be no transport keys in the database
|
|
||||||
assertEquals(emptyList(), db.getTransportKeys(txn, transportId));
|
|
||||||
|
|
||||||
// Add the contact, the transport and the unbound transport keys
|
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
|
||||||
assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
|
|
||||||
true, true));
|
|
||||||
db.addTransport(txn, transportId, 123);
|
|
||||||
assertEquals(keySetId, db.addTransportKeys(txn, null, keys));
|
|
||||||
assertEquals(keySetId1, db.addTransportKeys(txn, null, keys1));
|
|
||||||
|
|
||||||
// Retrieve the transport keys
|
|
||||||
Collection<KeySet> allKeys = db.getTransportKeys(txn, transportId);
|
|
||||||
assertEquals(2, allKeys.size());
|
|
||||||
for (KeySet ks : allKeys) {
|
|
||||||
assertNull(ks.getContactId());
|
|
||||||
if (ks.getKeySetId().equals(keySetId)) {
|
|
||||||
assertKeysEquals(keys, ks.getTransportKeys());
|
|
||||||
} else {
|
|
||||||
assertEquals(keySetId1, ks.getKeySetId());
|
|
||||||
assertKeysEquals(keys1, ks.getTransportKeys());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind the first set of transport keys
|
|
||||||
db.bindTransportKeys(txn, contactId, transportId, keySetId);
|
|
||||||
|
|
||||||
// Retrieve the keys again - the first set should be bound
|
|
||||||
allKeys = db.getTransportKeys(txn, transportId);
|
|
||||||
assertEquals(2, allKeys.size());
|
|
||||||
for (KeySet ks : allKeys) {
|
|
||||||
if (ks.getKeySetId().equals(keySetId)) {
|
|
||||||
assertEquals(contactId, ks.getContactId());
|
|
||||||
assertKeysEquals(keys, ks.getTransportKeys());
|
|
||||||
} else {
|
|
||||||
assertEquals(keySetId1, ks.getKeySetId());
|
|
||||||
assertNull(ks.getContactId());
|
|
||||||
assertKeysEquals(keys1, ks.getTransportKeys());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rotate the transport keys
|
|
||||||
TransportKeys rotated = createTransportKeys(rotationPeriod + 1);
|
|
||||||
TransportKeys rotated1 = createTransportKeys(rotationPeriod1 + 1);
|
|
||||||
db.updateTransportKeys(txn, new KeySet(keySetId, contactId, rotated));
|
|
||||||
db.updateTransportKeys(txn, new KeySet(keySetId1, null, rotated1));
|
|
||||||
|
|
||||||
// Retrieve the transport keys again
|
|
||||||
allKeys = db.getTransportKeys(txn, transportId);
|
|
||||||
assertEquals(2, allKeys.size());
|
|
||||||
for (KeySet ks : allKeys) {
|
|
||||||
if (ks.getKeySetId().equals(keySetId)) {
|
|
||||||
assertEquals(contactId, ks.getContactId());
|
|
||||||
assertKeysEquals(rotated, ks.getTransportKeys());
|
|
||||||
} else {
|
|
||||||
assertEquals(keySetId1, ks.getKeySetId());
|
|
||||||
assertNull(ks.getContactId());
|
|
||||||
assertKeysEquals(rotated1, ks.getTransportKeys());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the unbound transport keys
|
|
||||||
db.removeTransportKeys(txn, transportId, keySetId1);
|
|
||||||
|
|
||||||
// Retrieve the keys again - the second set should be gone
|
|
||||||
allKeys = db.getTransportKeys(txn, transportId);
|
|
||||||
assertEquals(1, allKeys.size());
|
|
||||||
KeySet ks = allKeys.iterator().next();
|
|
||||||
assertEquals(keySetId, ks.getKeySetId());
|
|
||||||
assertEquals(contactId, ks.getContactId());
|
|
||||||
assertKeysEquals(rotated, ks.getTransportKeys());
|
|
||||||
|
|
||||||
// Removing the transport should remove the remaining transport keys
|
|
||||||
db.removeTransport(txn, transportId);
|
|
||||||
assertEquals(emptyList(), db.getTransportKeys(txn, transportId));
|
|
||||||
|
|
||||||
db.commitTransaction(txn);
|
|
||||||
db.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertKeysEquals(TransportKeys expected,
|
private void assertKeysEquals(TransportKeys expected,
|
||||||
TransportKeys actual) {
|
TransportKeys actual) {
|
||||||
assertEquals(expected.getTransportId(), actual.getTransportId());
|
assertEquals(expected.getTransportId(), actual.getTransportId());
|
||||||
@@ -853,7 +767,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testIncrementStreamCounter() throws Exception {
|
public void testIncrementStreamCounter() throws Exception {
|
||||||
long rotationPeriod = 123;
|
long rotationPeriod = 123;
|
||||||
TransportKeys keys = createTransportKeys(rotationPeriod);
|
TransportKeys keys = createTransportKeys(rotationPeriod, true);
|
||||||
long streamCounter = keys.getCurrentOutgoingKeys().getStreamCounter();
|
long streamCounter = keys.getCurrentOutgoingKeys().getStreamCounter();
|
||||||
|
|
||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
@@ -893,8 +807,9 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetReorderingWindow() throws Exception {
|
public void testSetReorderingWindow() throws Exception {
|
||||||
|
boolean active = random.nextBoolean();
|
||||||
long rotationPeriod = 123;
|
long rotationPeriod = 123;
|
||||||
TransportKeys keys = createTransportKeys(rotationPeriod);
|
TransportKeys keys = createTransportKeys(rotationPeriod, active);
|
||||||
long base = keys.getCurrentIncomingKeys().getWindowBase();
|
long base = keys.getCurrentIncomingKeys().getWindowBase();
|
||||||
byte[] bitmap = keys.getCurrentIncomingKeys().getWindowBitmap();
|
byte[] bitmap = keys.getCurrentIncomingKeys().getWindowBitmap();
|
||||||
|
|
||||||
@@ -904,12 +819,12 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
// Add the contact, transport and transport keys
|
// Add the contact, transport and transport keys
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
db.addLocalAuthor(txn, localAuthor);
|
||||||
assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
|
assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
|
||||||
true, true));
|
true, active));
|
||||||
db.addTransport(txn, transportId, 123);
|
db.addTransport(txn, transportId, 123);
|
||||||
assertEquals(keySetId, db.addTransportKeys(txn, contactId, keys));
|
assertEquals(keySetId, db.addTransportKeys(txn, contactId, keys));
|
||||||
|
|
||||||
// Update the reordering window and retrieve the transport keys
|
// Update the reordering window and retrieve the transport keys
|
||||||
new Random().nextBytes(bitmap);
|
random.nextBytes(bitmap);
|
||||||
db.setReorderingWindow(txn, keySetId, transportId, rotationPeriod,
|
db.setReorderingWindow(txn, keySetId, transportId, rotationPeriod,
|
||||||
base + 1, bitmap);
|
base + 1, bitmap);
|
||||||
Collection<KeySet> newKeys = db.getTransportKeys(txn, transportId);
|
Collection<KeySet> newKeys = db.getTransportKeys(txn, transportId);
|
||||||
@@ -1908,7 +1823,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransportKeys createTransportKeys(long rotationPeriod) {
|
private TransportKeys createTransportKeys(long rotationPeriod,
|
||||||
|
boolean active) {
|
||||||
SecretKey inPrevTagKey = getSecretKey();
|
SecretKey inPrevTagKey = getSecretKey();
|
||||||
SecretKey inPrevHeaderKey = getSecretKey();
|
SecretKey inPrevHeaderKey = getSecretKey();
|
||||||
IncomingKeys inPrev = new IncomingKeys(inPrevTagKey, inPrevHeaderKey,
|
IncomingKeys inPrev = new IncomingKeys(inPrevTagKey, inPrevHeaderKey,
|
||||||
@@ -1924,7 +1840,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
SecretKey outCurrTagKey = getSecretKey();
|
SecretKey outCurrTagKey = getSecretKey();
|
||||||
SecretKey outCurrHeaderKey = getSecretKey();
|
SecretKey outCurrHeaderKey = getSecretKey();
|
||||||
OutgoingKeys outCurr = new OutgoingKeys(outCurrTagKey, outCurrHeaderKey,
|
OutgoingKeys outCurr = new OutgoingKeys(outCurrTagKey, outCurrHeaderKey,
|
||||||
rotationPeriod, 456, true);
|
rotationPeriod, 456, active);
|
||||||
return new TransportKeys(transportId, inPrev, inCurr, inNext, outCurr);
|
return new TransportKeys(transportId, inPrev, inCurr, inNext, outCurr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
@@ -54,6 +55,7 @@ public class KeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
new StreamContext(contactId, transportId, getSecretKey(),
|
new StreamContext(contactId, transportId, getSecretKey(),
|
||||||
getSecretKey(), 1);
|
getSecretKey(), 1);
|
||||||
private final byte[] tag = getRandomBytes(TAG_LENGTH);
|
private final byte[] tag = getRandomBytes(TAG_LENGTH);
|
||||||
|
private final Random random = new Random();
|
||||||
|
|
||||||
private final KeyManagerImpl keyManager = new KeyManagerImpl(db, executor,
|
private final KeyManagerImpl keyManager = new KeyManagerImpl(db, executor,
|
||||||
pluginConfig, transportKeyManagerFactory);
|
pluginConfig, transportKeyManagerFactory);
|
||||||
@@ -102,30 +104,18 @@ public class KeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
public void testAddContact() throws Exception {
|
public void testAddContact() throws Exception {
|
||||||
SecretKey secretKey = getSecretKey();
|
SecretKey secretKey = getSecretKey();
|
||||||
long timestamp = System.currentTimeMillis();
|
long timestamp = System.currentTimeMillis();
|
||||||
boolean alice = new Random().nextBoolean();
|
boolean alice = random.nextBoolean();
|
||||||
|
boolean active = random.nextBoolean();
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(transportKeyManager).addContact(txn, contactId, secretKey,
|
oneOf(transportKeyManager).addContact(txn, contactId, secretKey,
|
||||||
timestamp, alice);
|
timestamp, alice, active);
|
||||||
}});
|
|
||||||
|
|
||||||
keyManager.addContact(txn, contactId, secretKey, timestamp, alice);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAddUnboundKeys() throws Exception {
|
|
||||||
SecretKey secretKey = getSecretKey();
|
|
||||||
long timestamp = System.currentTimeMillis();
|
|
||||||
boolean alice = new Random().nextBoolean();
|
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(transportKeyManager).addUnboundKeys(txn, secretKey,
|
|
||||||
timestamp, alice);
|
|
||||||
will(returnValue(keySetId));
|
will(returnValue(keySetId));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
assertEquals(singletonMap(transportId, keySetId),
|
Map<TransportId, KeySetId> ids = keyManager.addContact(txn, contactId,
|
||||||
keyManager.addUnboundKeys(txn, secretKey, timestamp, alice));
|
secretKey, timestamp, alice, active);
|
||||||
|
assertEquals(singletonMap(transportId, keySetId), ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
private final ContactId contactId1 = new ContactId(234);
|
private final ContactId contactId1 = new ContactId(234);
|
||||||
private final KeySetId keySetId = new KeySetId(345);
|
private final KeySetId keySetId = new KeySetId(345);
|
||||||
private final KeySetId keySetId1 = new KeySetId(456);
|
private final KeySetId keySetId1 = new KeySetId(456);
|
||||||
private final KeySetId keySetId2 = new KeySetId(567);
|
|
||||||
private final SecretKey tagKey = TestUtils.getSecretKey();
|
private final SecretKey tagKey = TestUtils.getSecretKey();
|
||||||
private final SecretKey headerKey = TestUtils.getSecretKey();
|
private final SecretKey headerKey = TestUtils.getSecretKey();
|
||||||
private final SecretKey masterKey = TestUtils.getSecretKey();
|
private final SecretKey masterKey = TestUtils.getSecretKey();
|
||||||
@@ -71,14 +70,11 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
public void testKeysAreRotatedAtStartup() throws Exception {
|
public void testKeysAreRotatedAtStartup() throws Exception {
|
||||||
TransportKeys shouldRotate = createTransportKeys(900, 0, true);
|
TransportKeys shouldRotate = createTransportKeys(900, 0, true);
|
||||||
TransportKeys shouldNotRotate = createTransportKeys(1000, 0, true);
|
TransportKeys shouldNotRotate = createTransportKeys(1000, 0, true);
|
||||||
TransportKeys shouldRotate1 = createTransportKeys(999, 0, false);
|
|
||||||
Collection<KeySet> loaded = asList(
|
Collection<KeySet> loaded = asList(
|
||||||
new KeySet(keySetId, contactId, shouldRotate),
|
new KeySet(keySetId, contactId, shouldRotate),
|
||||||
new KeySet(keySetId1, contactId1, shouldNotRotate),
|
new KeySet(keySetId1, contactId1, shouldNotRotate)
|
||||||
new KeySet(keySetId2, null, shouldRotate1)
|
|
||||||
);
|
);
|
||||||
TransportKeys rotated = createTransportKeys(1000, 0, true);
|
TransportKeys rotated = createTransportKeys(1000, 0, true);
|
||||||
TransportKeys rotated1 = createTransportKeys(1000, 0, false);
|
|
||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
@@ -93,8 +89,6 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
will(returnValue(rotated));
|
will(returnValue(rotated));
|
||||||
oneOf(transportCrypto).rotateTransportKeys(shouldNotRotate, 1000);
|
oneOf(transportCrypto).rotateTransportKeys(shouldNotRotate, 1000);
|
||||||
will(returnValue(shouldNotRotate));
|
will(returnValue(shouldNotRotate));
|
||||||
oneOf(transportCrypto).rotateTransportKeys(shouldRotate1, 1000);
|
|
||||||
will(returnValue(rotated1));
|
|
||||||
// Encode the tags (3 sets per contact)
|
// Encode the tags (3 sets per contact)
|
||||||
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
||||||
exactly(6).of(transportCrypto).encodeTag(
|
exactly(6).of(transportCrypto).encodeTag(
|
||||||
@@ -103,10 +97,8 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
will(new EncodeTagAction());
|
will(new EncodeTagAction());
|
||||||
}
|
}
|
||||||
// Save the keys that were rotated
|
// Save the keys that were rotated
|
||||||
oneOf(db).updateTransportKeys(txn, asList(
|
oneOf(db).updateTransportKeys(txn,
|
||||||
new KeySet(keySetId, contactId, rotated),
|
singletonList(new KeySet(keySetId, contactId, rotated)));
|
||||||
new KeySet(keySetId2, null, rotated1))
|
|
||||||
);
|
|
||||||
// Schedule key rotation at the start of the next rotation period
|
// Schedule key rotation at the start of the next rotation period
|
||||||
oneOf(scheduler).schedule(with(any(Runnable.class)),
|
oneOf(scheduler).schedule(with(any(Runnable.class)),
|
||||||
with(rotationPeriodLength - 1), with(MILLISECONDS));
|
with(rotationPeriodLength - 1), with(MILLISECONDS));
|
||||||
@@ -153,43 +145,11 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
maxLatency);
|
maxLatency);
|
||||||
// The timestamp is 1 ms before the start of rotation period 1000
|
// The timestamp is 1 ms before the start of rotation period 1000
|
||||||
long timestamp = rotationPeriodLength * 1000 - 1;
|
long timestamp = rotationPeriodLength * 1000 - 1;
|
||||||
transportKeyManager.addContact(txn, contactId, masterKey, timestamp,
|
assertEquals(keySetId, transportKeyManager.addContact(txn, contactId,
|
||||||
alice);
|
masterKey, timestamp, alice, true));
|
||||||
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testKeysAreRotatedWhenAddingUnboundKeys() throws Exception {
|
|
||||||
boolean alice = random.nextBoolean();
|
|
||||||
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, false);
|
|
||||||
will(returnValue(transportKeys));
|
|
||||||
// Get the current time (1 ms after start of rotation period 1000)
|
|
||||||
oneOf(clock).currentTimeMillis();
|
|
||||||
will(returnValue(rotationPeriodLength * 1000 + 1));
|
|
||||||
// Rotate the transport keys
|
|
||||||
oneOf(transportCrypto).rotateTransportKeys(transportKeys, 1000);
|
|
||||||
will(returnValue(rotated));
|
|
||||||
// Save the keys
|
|
||||||
oneOf(db).addTransportKeys(txn, null, rotated);
|
|
||||||
will(returnValue(keySetId));
|
|
||||||
}});
|
|
||||||
|
|
||||||
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
|
||||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
|
||||||
maxLatency);
|
|
||||||
// The timestamp is 1 ms before the start of rotation period 1000
|
|
||||||
long timestamp = rotationPeriodLength * 1000 - 1;
|
|
||||||
assertEquals(keySetId, transportKeyManager.addUnboundKeys(txn,
|
|
||||||
masterKey, timestamp, alice));
|
|
||||||
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOutgoingStreamContextIsNullIfContactIsNotFound()
|
public void testOutgoingStreamContextIsNullIfContactIsNotFound()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -211,15 +171,15 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
MAX_32_BIT_UNSIGNED + 1, true);
|
MAX_32_BIT_UNSIGNED + 1, true);
|
||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
|
|
||||||
expectAddContactNoRotation(alice, transportKeys, txn);
|
expectAddContactNoRotation(alice, true, transportKeys, txn);
|
||||||
|
|
||||||
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
||||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
||||||
maxLatency);
|
maxLatency);
|
||||||
// The timestamp is at the start of rotation period 1000
|
// The timestamp is at the start of rotation period 1000
|
||||||
long timestamp = rotationPeriodLength * 1000;
|
long timestamp = rotationPeriodLength * 1000;
|
||||||
transportKeyManager.addContact(txn, contactId, masterKey, timestamp,
|
assertEquals(keySetId, transportKeyManager.addContact(txn, contactId,
|
||||||
alice);
|
masterKey, timestamp, alice, true));
|
||||||
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
||||||
}
|
}
|
||||||
@@ -232,7 +192,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
MAX_32_BIT_UNSIGNED, true);
|
MAX_32_BIT_UNSIGNED, true);
|
||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
|
|
||||||
expectAddContactNoRotation(alice, transportKeys, txn);
|
expectAddContactNoRotation(alice, true, transportKeys, txn);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Increment the stream counter
|
// Increment the stream counter
|
||||||
@@ -244,8 +204,8 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
maxLatency);
|
maxLatency);
|
||||||
// The timestamp is at the start of rotation period 1000
|
// The timestamp is at the start of rotation period 1000
|
||||||
long timestamp = rotationPeriodLength * 1000;
|
long timestamp = rotationPeriodLength * 1000;
|
||||||
transportKeyManager.addContact(txn, contactId, masterKey, timestamp,
|
assertEquals(keySetId, transportKeyManager.addContact(txn, contactId,
|
||||||
alice);
|
masterKey, timestamp, alice, true));
|
||||||
// The first request should return a stream context
|
// The first request should return a stream context
|
||||||
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
StreamContext ctx = transportKeyManager.getStreamContext(txn,
|
StreamContext ctx = transportKeyManager.getStreamContext(txn,
|
||||||
@@ -265,19 +225,21 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
public void testIncomingStreamContextIsNullIfTagIsNotFound()
|
public void testIncomingStreamContextIsNullIfTagIsNotFound()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
boolean alice = random.nextBoolean();
|
boolean alice = random.nextBoolean();
|
||||||
TransportKeys transportKeys = createTransportKeys(1000, 0, true);
|
boolean active = random.nextBoolean();
|
||||||
|
TransportKeys transportKeys = createTransportKeys(1000, 0, active);
|
||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
|
|
||||||
expectAddContactNoRotation(alice, transportKeys, txn);
|
expectAddContactNoRotation(alice, active, transportKeys, txn);
|
||||||
|
|
||||||
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
||||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
||||||
maxLatency);
|
maxLatency);
|
||||||
// The timestamp is at the start of rotation period 1000
|
// The timestamp is at the start of rotation period 1000
|
||||||
long timestamp = rotationPeriodLength * 1000;
|
long timestamp = rotationPeriodLength * 1000;
|
||||||
transportKeyManager.addContact(txn, contactId, masterKey, timestamp,
|
assertEquals(keySetId, transportKeyManager.addContact(txn, contactId,
|
||||||
alice);
|
masterKey, timestamp, alice, active));
|
||||||
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
assertEquals(active,
|
||||||
|
transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
// The tag should not be recognised
|
// The tag should not be recognised
|
||||||
assertNull(transportKeyManager.getStreamContext(txn,
|
assertNull(transportKeyManager.getStreamContext(txn,
|
||||||
new byte[TAG_LENGTH]));
|
new byte[TAG_LENGTH]));
|
||||||
@@ -327,8 +289,8 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
maxLatency);
|
maxLatency);
|
||||||
// The timestamp is at the start of rotation period 1000
|
// The timestamp is at the start of rotation period 1000
|
||||||
long timestamp = rotationPeriodLength * 1000;
|
long timestamp = rotationPeriodLength * 1000;
|
||||||
transportKeyManager.addContact(txn, contactId, masterKey, timestamp,
|
assertEquals(keySetId, transportKeyManager.addContact(txn, contactId,
|
||||||
alice);
|
masterKey, timestamp, alice, true));
|
||||||
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
// Use the first tag (previous rotation period, stream number 0)
|
// Use the first tag (previous rotation period, stream number 0)
|
||||||
assertEquals(REORDERING_WINDOW_SIZE * 3, tags.size());
|
assertEquals(REORDERING_WINDOW_SIZE * 3, tags.size());
|
||||||
@@ -415,23 +377,14 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBindingAndActivatingKeys() throws Exception {
|
public void testActivatingKeys() throws Exception {
|
||||||
boolean alice = random.nextBoolean();
|
boolean alice = random.nextBoolean();
|
||||||
TransportKeys transportKeys = createTransportKeys(1000, 0, false);
|
TransportKeys transportKeys = createTransportKeys(1000, 0, false);
|
||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
|
|
||||||
expectAddUnboundKeysNoRotation(alice, transportKeys, txn);
|
expectAddContactNoRotation(alice, false, transportKeys, txn);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// When the keys are bound, encode the tags (3 sets)
|
|
||||||
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
|
||||||
exactly(3).of(transportCrypto).encodeTag(
|
|
||||||
with(any(byte[].class)), with(tagKey),
|
|
||||||
with(PROTOCOL_VERSION), with(i));
|
|
||||||
will(new EncodeTagAction());
|
|
||||||
}
|
|
||||||
// Save the key binding
|
|
||||||
oneOf(db).bindTransportKeys(txn, contactId, transportId, keySetId);
|
|
||||||
// Activate the keys
|
// Activate the keys
|
||||||
oneOf(db).setTransportKeysActive(txn, transportId, keySetId);
|
oneOf(db).setTransportKeysActive(txn, transportId, keySetId);
|
||||||
// Increment the stream counter
|
// Increment the stream counter
|
||||||
@@ -443,12 +396,8 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
maxLatency);
|
maxLatency);
|
||||||
// The timestamp is at the start of rotation period 1000
|
// The timestamp is at the start of rotation period 1000
|
||||||
long timestamp = rotationPeriodLength * 1000;
|
long timestamp = rotationPeriodLength * 1000;
|
||||||
assertEquals(keySetId, transportKeyManager.addUnboundKeys(txn,
|
assertEquals(keySetId, transportKeyManager.addContact(txn, contactId,
|
||||||
masterKey, timestamp, alice));
|
masterKey, timestamp, alice, false));
|
||||||
// The keys are unbound so no stream context should be returned
|
|
||||||
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
|
||||||
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
|
||||||
transportKeyManager.bindKeys(txn, contactId, keySetId);
|
|
||||||
// The keys are inactive so no stream context should be returned
|
// The keys are inactive so no stream context should be returned
|
||||||
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
||||||
@@ -474,18 +423,26 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
// Keep a copy of the tags
|
// Keep a copy of the tags
|
||||||
List<byte[]> tags = new ArrayList<>();
|
List<byte[]> tags = new ArrayList<>();
|
||||||
|
|
||||||
expectAddUnboundKeysNoRotation(alice, transportKeys, txn);
|
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// When the keys are bound, encode the tags (3 sets)
|
oneOf(transportCrypto).deriveTransportKeys(transportId, masterKey,
|
||||||
|
1000, alice, false);
|
||||||
|
will(returnValue(transportKeys));
|
||||||
|
// Get the current time (the start of rotation period 1000)
|
||||||
|
oneOf(clock).currentTimeMillis();
|
||||||
|
will(returnValue(rotationPeriodLength * 1000));
|
||||||
|
// Encode the tags (3 sets)
|
||||||
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
||||||
exactly(3).of(transportCrypto).encodeTag(
|
exactly(3).of(transportCrypto).encodeTag(
|
||||||
with(any(byte[].class)), with(tagKey),
|
with(any(byte[].class)), with(tagKey),
|
||||||
with(PROTOCOL_VERSION), with(i));
|
with(PROTOCOL_VERSION), with(i));
|
||||||
will(new EncodeTagAction(tags));
|
will(new EncodeTagAction(tags));
|
||||||
}
|
}
|
||||||
// Save the key binding
|
// Rotate the transport keys (the keys are unaffected)
|
||||||
oneOf(db).bindTransportKeys(txn, contactId, transportId, keySetId);
|
oneOf(transportCrypto).rotateTransportKeys(transportKeys, 1000);
|
||||||
|
will(returnValue(transportKeys));
|
||||||
|
// Save the keys
|
||||||
|
oneOf(db).addTransportKeys(txn, contactId, transportKeys);
|
||||||
|
will(returnValue(keySetId));
|
||||||
// Encode a new tag after sliding the window
|
// Encode a new tag after sliding the window
|
||||||
oneOf(transportCrypto).encodeTag(with(any(byte[].class)),
|
oneOf(transportCrypto).encodeTag(with(any(byte[].class)),
|
||||||
with(tagKey), with(PROTOCOL_VERSION),
|
with(tagKey), with(PROTOCOL_VERSION),
|
||||||
@@ -505,9 +462,8 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
maxLatency);
|
maxLatency);
|
||||||
// The timestamp is at the start of rotation period 1000
|
// The timestamp is at the start of rotation period 1000
|
||||||
long timestamp = rotationPeriodLength * 1000;
|
long timestamp = rotationPeriodLength * 1000;
|
||||||
assertEquals(keySetId, transportKeyManager.addUnboundKeys(txn,
|
assertEquals(keySetId, transportKeyManager.addContact(txn, contactId,
|
||||||
masterKey, timestamp, alice));
|
masterKey, timestamp, alice, false));
|
||||||
transportKeyManager.bindKeys(txn, contactId, keySetId);
|
|
||||||
// The keys are inactive so no stream context should be returned
|
// The keys are inactive so no stream context should be returned
|
||||||
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
||||||
@@ -532,36 +488,11 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
assertEquals(0L, ctx.getStreamNumber());
|
assertEquals(0L, ctx.getStreamNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
private void expectAddContactNoRotation(boolean alice, boolean active,
|
||||||
public void testRemovingUnboundKeys() throws Exception {
|
|
||||||
boolean alice = random.nextBoolean();
|
|
||||||
TransportKeys transportKeys = createTransportKeys(1000, 0, false);
|
|
||||||
Transaction txn = new Transaction(null, false);
|
|
||||||
|
|
||||||
expectAddUnboundKeysNoRotation(alice, transportKeys, txn);
|
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
// Remove the unbound keys
|
|
||||||
oneOf(db).removeTransportKeys(txn, transportId, keySetId);
|
|
||||||
}});
|
|
||||||
|
|
||||||
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
|
||||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
|
||||||
maxLatency);
|
|
||||||
// The timestamp is at the start of rotation period 1000
|
|
||||||
long timestamp = rotationPeriodLength * 1000;
|
|
||||||
assertEquals(keySetId, transportKeyManager.addUnboundKeys(txn,
|
|
||||||
masterKey, timestamp, alice));
|
|
||||||
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
|
||||||
transportKeyManager.removeKeys(txn, keySetId);
|
|
||||||
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void expectAddContactNoRotation(boolean alice,
|
|
||||||
TransportKeys transportKeys, Transaction txn) throws Exception {
|
TransportKeys transportKeys, Transaction txn) throws Exception {
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(transportCrypto).deriveTransportKeys(transportId, masterKey,
|
oneOf(transportCrypto).deriveTransportKeys(transportId, masterKey,
|
||||||
1000, alice, true);
|
1000, alice, active);
|
||||||
will(returnValue(transportKeys));
|
will(returnValue(transportKeys));
|
||||||
// Get the current time (the start of rotation period 1000)
|
// Get the current time (the start of rotation period 1000)
|
||||||
oneOf(clock).currentTimeMillis();
|
oneOf(clock).currentTimeMillis();
|
||||||
@@ -582,24 +513,6 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expectAddUnboundKeysNoRotation(boolean alice,
|
|
||||||
TransportKeys transportKeys, Transaction txn) throws Exception {
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(transportCrypto).deriveTransportKeys(transportId, masterKey,
|
|
||||||
1000, alice, false);
|
|
||||||
will(returnValue(transportKeys));
|
|
||||||
// Get the current time (the start of rotation period 1000)
|
|
||||||
oneOf(clock).currentTimeMillis();
|
|
||||||
will(returnValue(rotationPeriodLength * 1000));
|
|
||||||
// Rotate the transport keys (the keys are unaffected)
|
|
||||||
oneOf(transportCrypto).rotateTransportKeys(transportKeys, 1000);
|
|
||||||
will(returnValue(transportKeys));
|
|
||||||
// Save the unbound keys
|
|
||||||
oneOf(db).addTransportKeys(txn, null, transportKeys);
|
|
||||||
will(returnValue(keySetId));
|
|
||||||
}});
|
|
||||||
}
|
|
||||||
|
|
||||||
private TransportKeys createTransportKeys(long rotationPeriod,
|
private TransportKeys createTransportKeys(long rotationPeriod,
|
||||||
long streamCounter, boolean active) {
|
long streamCounter, boolean active) {
|
||||||
IncomingKeys inPrev = new IncomingKeys(tagKey, headerKey,
|
IncomingKeys inPrev = new IncomingKeys(tagKey, headerKey,
|
||||||
|
|||||||
@@ -453,12 +453,11 @@ class IntroduceeProtocolEngine
|
|||||||
.getContact(txn, s.getRemote().author.getId(),
|
.getContact(txn, s.getRemote().author.getId(),
|
||||||
localAuthor.getId());
|
localAuthor.getId());
|
||||||
|
|
||||||
// bind the keys to the new contact
|
// add the keys to the new contact
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
keys = keyManager
|
keys = keyManager
|
||||||
.addUnboundKeys(txn, new SecretKey(s.getMasterKey()),
|
.addContact(txn, c.getId(), new SecretKey(s.getMasterKey()),
|
||||||
timestamp, s.getLocal().alice);
|
timestamp, s.getLocal().alice, false);
|
||||||
keyManager.bindKeys(txn, c.getId(), keys);
|
|
||||||
|
|
||||||
// add signed transport properties for the contact
|
// add signed transport properties for the contact
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
|
|||||||
Reference in New Issue
Block a user