mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 06:09:55 +01:00
Store the incoming and outgoing secrets separately.
This commit is contained in:
@@ -9,20 +9,16 @@ import javax.crypto.Mac;
|
|||||||
|
|
||||||
public interface CryptoComponent {
|
public interface CryptoComponent {
|
||||||
|
|
||||||
ErasableKey deriveIncomingFrameKey(byte[] secret);
|
ErasableKey deriveFrameKey(byte[] source, boolean initiator);
|
||||||
|
|
||||||
ErasableKey deriveIncomingIvKey(byte[] secret);
|
ErasableKey deriveIvKey(byte[] source, boolean initiator);
|
||||||
|
|
||||||
ErasableKey deriveIncomingMacKey(byte[] secret);
|
ErasableKey deriveMacKey(byte[] source, boolean initiator);
|
||||||
|
|
||||||
ErasableKey deriveOutgoingFrameKey(byte[] secret);
|
|
||||||
|
|
||||||
ErasableKey deriveOutgoingIvKey(byte[] secret);
|
|
||||||
|
|
||||||
ErasableKey deriveOutgoingMacKey(byte[] secret);
|
|
||||||
|
|
||||||
KeyPair generateKeyPair();
|
KeyPair generateKeyPair();
|
||||||
|
|
||||||
|
ErasableKey generateTestKey();
|
||||||
|
|
||||||
Cipher getFrameCipher();
|
Cipher getFrameCipher();
|
||||||
|
|
||||||
Cipher getIvCipher();
|
Cipher getIvCipher();
|
||||||
@@ -36,6 +32,4 @@ public interface CryptoComponent {
|
|||||||
SecureRandom getSecureRandom();
|
SecureRandom getSecureRandom();
|
||||||
|
|
||||||
Signature getSignature();
|
Signature getSignature();
|
||||||
|
|
||||||
ErasableKey generateTestKey();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,10 +53,11 @@ public interface DatabaseComponent {
|
|||||||
void removeListener(DatabaseListener d);
|
void removeListener(DatabaseListener d);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new contact to the database with the given secret and returns an
|
* Adds a new contact to the database with the given secrets and returns an
|
||||||
* ID for the contact.
|
* ID for the contact.
|
||||||
*/
|
*/
|
||||||
ContactId addContact(byte[] secret) throws DbException;
|
ContactId addContact(byte[] incomingSecret, byte[] outgoingSecret)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/** Adds a locally generated group message to the database. */
|
/** Adds a locally generated group message to the database. */
|
||||||
void addLocalGroupMessage(Message m) throws DbException;
|
void addLocalGroupMessage(Message m) throws DbException;
|
||||||
@@ -158,7 +159,7 @@ public interface DatabaseComponent {
|
|||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/** Returns the secret shared with the given contact. */
|
/** Returns the secret shared with the given contact. */
|
||||||
byte[] getSharedSecret(ContactId c) throws DbException;
|
byte[] getSharedSecret(ContactId c, boolean incoming) throws DbException;
|
||||||
|
|
||||||
/** Returns the set of groups to which the user subscribes. */
|
/** Returns the set of groups to which the user subscribes. */
|
||||||
Collection<Group> getSubscriptions() throws DbException;
|
Collection<Group> getSubscriptions() throws DbException;
|
||||||
|
|||||||
@@ -8,14 +8,15 @@ public interface ConnectionReaderFactory {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a connection reader for a batch-mode connection or the
|
* Creates a connection reader for a batch-mode connection or the
|
||||||
* initiator's side of a stream-mode connection.
|
* initiator's side of a stream-mode connection. The secret is erased before
|
||||||
|
* returning.
|
||||||
*/
|
*/
|
||||||
ConnectionReader createConnectionReader(InputStream in, TransportIndex i,
|
ConnectionReader createConnectionReader(InputStream in, TransportIndex i,
|
||||||
byte[] encryptedIv, byte[] secret);
|
byte[] encryptedIv, byte[] secret);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a connection reader for the responder's side of a stream-mode
|
* Creates a connection reader for the responder's side of a stream-mode
|
||||||
* connection.
|
* connection. The secret is erased before returning.
|
||||||
*/
|
*/
|
||||||
ConnectionReader createConnectionReader(InputStream in, TransportIndex i,
|
ConnectionReader createConnectionReader(InputStream in, TransportIndex i,
|
||||||
long connection, byte[] secret);
|
long connection, byte[] secret);
|
||||||
|
|||||||
@@ -8,14 +8,15 @@ public interface ConnectionWriterFactory {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a connection writer for a batch-mode connection or the
|
* Creates a connection writer for a batch-mode connection or the
|
||||||
* initiator's side of a stream-mode connection.
|
* initiator's side of a stream-mode connection. The secret is erased before
|
||||||
|
* returning.
|
||||||
*/
|
*/
|
||||||
ConnectionWriter createConnectionWriter(OutputStream out, long capacity,
|
ConnectionWriter createConnectionWriter(OutputStream out, long capacity,
|
||||||
TransportIndex i, long connection, byte[] secret);
|
TransportIndex i, long connection, byte[] secret);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a connection writer for the responder's side of a stream-mode
|
* Creates a connection writer for the responder's side of a stream-mode
|
||||||
* connection.
|
* connection. The secret is erased before returning.
|
||||||
*/
|
*/
|
||||||
ConnectionWriter createConnectionWriter(OutputStream out, long capacity,
|
ConnectionWriter createConnectionWriter(OutputStream out, long capacity,
|
||||||
TransportIndex i, byte[] encryptedIv, byte[] secret);
|
TransportIndex i, byte[] encryptedIv, byte[] secret);
|
||||||
|
|||||||
@@ -53,17 +53,22 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ErasableKey deriveIncomingFrameKey(byte[] secret) {
|
public ErasableKey deriveFrameKey(byte[] source, boolean initiator) {
|
||||||
SharedSecret s = new SharedSecret(secret);
|
if(initiator) return deriveKey("FRAME_I", source);
|
||||||
return deriveFrameKey(s, !s.getAlice());
|
else return deriveKey("FRAME_R", source);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ErasableKey deriveFrameKey(SharedSecret s, boolean alice) {
|
public ErasableKey deriveIvKey(byte[] source, boolean initiator) {
|
||||||
if(alice) return deriveKey("F_A", s.getSecret());
|
if(initiator) return deriveKey("IV_I", source);
|
||||||
else return deriveKey("F_B", s.getSecret());
|
else return deriveKey("IV_R", source);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ErasableKey deriveKey(String name, byte[] secret) {
|
public ErasableKey deriveMacKey(byte[] source, boolean initiator) {
|
||||||
|
if(initiator) return deriveKey("MAC_I", source);
|
||||||
|
else return deriveKey("MAC_R", source);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ErasableKey deriveKey(String name, byte[] source) {
|
||||||
MessageDigest digest = getMessageDigest();
|
MessageDigest digest = getMessageDigest();
|
||||||
assert digest.getDigestLength() == SECRET_KEY_BYTES;
|
assert digest.getDigestLength() == SECRET_KEY_BYTES;
|
||||||
try {
|
try {
|
||||||
@@ -71,49 +76,20 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
} catch(UnsupportedEncodingException e) {
|
} catch(UnsupportedEncodingException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
digest.update(secret);
|
digest.update(source);
|
||||||
return new ErasableKeyImpl(digest.digest(), SECRET_KEY_ALGO);
|
return new ErasableKeyImpl(digest.digest(), SECRET_KEY_ALGO);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ErasableKey deriveIncomingIvKey(byte[] secret) {
|
|
||||||
SharedSecret s = new SharedSecret(secret);
|
|
||||||
return deriveIvKey(s, !s.getAlice());
|
|
||||||
}
|
|
||||||
|
|
||||||
private ErasableKey deriveIvKey(SharedSecret s, boolean alice) {
|
|
||||||
if(alice) return deriveKey("I_A", s.getSecret());
|
|
||||||
else return deriveKey("I_B", s.getSecret());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ErasableKey deriveIncomingMacKey(byte[] secret) {
|
|
||||||
SharedSecret s = new SharedSecret(secret);
|
|
||||||
return deriveMacKey(s, !s.getAlice());
|
|
||||||
}
|
|
||||||
|
|
||||||
private ErasableKey deriveMacKey(SharedSecret s, boolean alice) {
|
|
||||||
if(alice) return deriveKey("M_A", s.getSecret());
|
|
||||||
else return deriveKey("M_B", s.getSecret());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ErasableKey deriveOutgoingFrameKey(byte[] secret) {
|
|
||||||
SharedSecret s = new SharedSecret(secret);
|
|
||||||
return deriveFrameKey(s, s.getAlice());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ErasableKey deriveOutgoingIvKey(byte[] secret) {
|
|
||||||
SharedSecret s = new SharedSecret(secret);
|
|
||||||
return deriveIvKey(s, s.getAlice());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ErasableKey deriveOutgoingMacKey(byte[] secret) {
|
|
||||||
SharedSecret s = new SharedSecret(secret);
|
|
||||||
return deriveMacKey(s, s.getAlice());
|
|
||||||
}
|
|
||||||
|
|
||||||
public KeyPair generateKeyPair() {
|
public KeyPair generateKeyPair() {
|
||||||
return keyPairGenerator.generateKeyPair();
|
return keyPairGenerator.generateKeyPair();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ErasableKey generateTestKey() {
|
||||||
|
byte[] b = new byte[SECRET_KEY_BYTES];
|
||||||
|
getSecureRandom().nextBytes(b);
|
||||||
|
return new ErasableKeyImpl(b, SECRET_KEY_ALGO);
|
||||||
|
}
|
||||||
|
|
||||||
public Cipher getFrameCipher() {
|
public Cipher getFrameCipher() {
|
||||||
try {
|
try {
|
||||||
return Cipher.getInstance(FRAME_CIPHER_ALGO, PROVIDER);
|
return Cipher.getInstance(FRAME_CIPHER_ALGO, PROVIDER);
|
||||||
@@ -177,10 +153,4 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ErasableKey generateTestKey() {
|
|
||||||
byte[] b = new byte[SECRET_KEY_BYTES];
|
|
||||||
getSecureRandom().nextBytes(b);
|
|
||||||
return new ErasableKeyImpl(b, SECRET_KEY_ALGO);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
package net.sf.briar.crypto;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A shared secret from which authentication and encryption keys can be derived.
|
|
||||||
* The secret carries a flag indicating whether Alice's keys or Bob's keys
|
|
||||||
* should be derived from the secret. When two parties agree on a shared secret,
|
|
||||||
* they must decide which of them will derive Alice's keys and which Bob's.
|
|
||||||
*/
|
|
||||||
class SharedSecret {
|
|
||||||
|
|
||||||
private final boolean alice;
|
|
||||||
private final byte[] secret;
|
|
||||||
|
|
||||||
SharedSecret(byte[] b) {
|
|
||||||
if(b.length < 2) throw new IllegalArgumentException();
|
|
||||||
switch(b[0]) {
|
|
||||||
case 0:
|
|
||||||
alice = false;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
alice = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
secret = new byte[b.length - 1];
|
|
||||||
System.arraycopy(b, 1, secret, 0, secret.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedSecret(boolean alice, byte[] secret) {
|
|
||||||
this.alice = alice;
|
|
||||||
this.secret = secret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if we should play the role of Alice in connections using
|
|
||||||
* this secret, or false if we should play the role of Bob.
|
|
||||||
*/
|
|
||||||
boolean getAlice() {
|
|
||||||
return alice;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the shared secret. */
|
|
||||||
byte[] getSecret() {
|
|
||||||
return secret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a raw representation of this object, suitable for storing in the
|
|
||||||
* database.
|
|
||||||
*/
|
|
||||||
byte[] getBytes() {
|
|
||||||
byte[] b = new byte[1 + secret.length];
|
|
||||||
if(alice) b[0] = (byte) 1;
|
|
||||||
System.arraycopy(secret, 0, b, 1, secret.length);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -80,12 +80,13 @@ interface Database<T> {
|
|||||||
void addBatchToAck(T txn, ContactId c, BatchId b) throws DbException;
|
void addBatchToAck(T txn, ContactId c, BatchId b) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new contact to the database with the given secret and returns an
|
* Adds a new contact to the database with the given secrets and returns an
|
||||||
* ID for the contact.
|
* ID for the contact.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: contact write.
|
* Locking: contact write.
|
||||||
*/
|
*/
|
||||||
ContactId addContact(T txn, byte[] secret) throws DbException;
|
ContactId addContact(T txn, byte[] incomingSecret, byte[] outgoingSecret)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns false if the given message is already in the database. Otherwise
|
* Returns false if the given message is already in the database. Otherwise
|
||||||
@@ -376,7 +377,8 @@ interface Database<T> {
|
|||||||
* <p>
|
* <p>
|
||||||
* Locking: contact read.
|
* Locking: contact read.
|
||||||
*/
|
*/
|
||||||
byte[] getSharedSecret(T txn, ContactId c) throws DbException;
|
byte[] getSharedSecret(T txn, ContactId c, boolean incoming)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the given message has been starred.
|
* Returns true if the given message has been starred.
|
||||||
|
|||||||
@@ -135,14 +135,15 @@ DatabaseCleaner.Callback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContactId addContact(byte[] secret) throws DbException {
|
public ContactId addContact(byte[] incomingSecret, byte[] outgoingSecret)
|
||||||
|
throws DbException {
|
||||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Adding contact");
|
if(LOG.isLoggable(Level.FINE)) LOG.fine("Adding contact");
|
||||||
ContactId c;
|
ContactId c;
|
||||||
contactLock.writeLock().lock();
|
contactLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
c = db.addContact(txn, secret);
|
c = db.addContact(txn, incomingSecret, outgoingSecret);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Added contact " + c);
|
if(LOG.isLoggable(Level.FINE)) LOG.fine("Added contact " + c);
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
@@ -905,13 +906,14 @@ DatabaseCleaner.Callback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getSharedSecret(ContactId c) throws DbException {
|
public byte[] getSharedSecret(ContactId c, boolean incoming)
|
||||||
|
throws DbException {
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
if(!containsContact(c)) throw new NoSuchContactException();
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
byte[] secret = db.getSharedSecret(txn, c);
|
byte[] secret = db.getSharedSecret(txn, c, incoming);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
return secret;
|
return secret;
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
private static final String CREATE_CONTACTS =
|
private static final String CREATE_CONTACTS =
|
||||||
"CREATE TABLE contacts"
|
"CREATE TABLE contacts"
|
||||||
+ " (contactId COUNTER,"
|
+ " (contactId COUNTER,"
|
||||||
+ " secret BINARY NOT NULL,"
|
+ " incomingSecret BINARY NOT NULL,"
|
||||||
|
+ " outgoingSecret BINARY NOT NULL,"
|
||||||
+ " PRIMARY KEY (contactId))";
|
+ " PRIMARY KEY (contactId))";
|
||||||
|
|
||||||
private static final String CREATE_MESSAGES =
|
private static final String CREATE_MESSAGES =
|
||||||
@@ -509,15 +510,17 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContactId addContact(Connection txn, byte[] secret)
|
public ContactId addContact(Connection txn, byte[] incomingSecret,
|
||||||
throws DbException {
|
byte[] outgoingSecret) throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
// Create a new contact row
|
// Create a new contact row
|
||||||
String sql = "INSERT INTO contacts (secret) VALUES (?)";
|
String sql = "INSERT INTO contacts (incomingSecret, outgoingSecret)"
|
||||||
|
+ " VALUES (?, ?)";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, secret);
|
ps.setBytes(1, incomingSecret);
|
||||||
|
ps.setBytes(2, outgoingSecret);
|
||||||
int affected = ps.executeUpdate();
|
int affected = ps.executeUpdate();
|
||||||
if(affected != 1) throw new DbStateException();
|
if(affected != 1) throw new DbStateException();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -1643,12 +1646,13 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getSharedSecret(Connection txn, ContactId c)
|
public byte[] getSharedSecret(Connection txn, ContactId c, boolean incoming)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT secret FROM contacts WHERE contactId = ?";
|
String col = incoming ? "incomingSecret" : "outgoingSecret";
|
||||||
|
String sql = "SELECT " + col + " FROM contacts WHERE contactId = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setInt(1, c.getInt());
|
ps.setInt(1, c.getInt());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
|
|||||||
TransportIndex i, byte[] encryptedIv, byte[] secret) {
|
TransportIndex i, byte[] encryptedIv, byte[] secret) {
|
||||||
// Decrypt the IV
|
// Decrypt the IV
|
||||||
Cipher ivCipher = crypto.getIvCipher();
|
Cipher ivCipher = crypto.getIvCipher();
|
||||||
ErasableKey ivKey = crypto.deriveIncomingIvKey(secret);
|
ErasableKey ivKey = crypto.deriveIvKey(secret, true);
|
||||||
byte[] iv;
|
byte[] iv;
|
||||||
try {
|
try {
|
||||||
ivCipher.init(Cipher.DECRYPT_MODE, ivKey);
|
ivCipher.init(Cipher.DECRYPT_MODE, ivKey);
|
||||||
@@ -57,15 +57,17 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
|
|||||||
private ConnectionReader createConnectionReader(InputStream in,
|
private ConnectionReader createConnectionReader(InputStream in,
|
||||||
boolean initiator, TransportIndex i, long connection,
|
boolean initiator, TransportIndex i, long connection,
|
||||||
byte[] secret) {
|
byte[] secret) {
|
||||||
byte[] iv = IvEncoder.encodeIv(initiator, i, connection);
|
// Derive the keys and erase the secret
|
||||||
|
ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator);
|
||||||
|
ErasableKey macKey = crypto.deriveMacKey(secret, initiator);
|
||||||
|
for(int j = 0; j < secret.length; j++) secret[j] = 0;
|
||||||
// Create the decrypter
|
// Create the decrypter
|
||||||
|
byte[] iv = IvEncoder.encodeIv(initiator, i, connection);
|
||||||
Cipher frameCipher = crypto.getFrameCipher();
|
Cipher frameCipher = crypto.getFrameCipher();
|
||||||
ErasableKey frameKey = crypto.deriveIncomingFrameKey(secret);
|
|
||||||
ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in, iv,
|
ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in, iv,
|
||||||
frameCipher, frameKey);
|
frameCipher, frameKey);
|
||||||
// Create the reader
|
// Create the reader
|
||||||
Mac mac = crypto.getMac();
|
Mac mac = crypto.getMac();
|
||||||
ErasableKey macKey = crypto.deriveIncomingMacKey(secret);
|
|
||||||
return new ConnectionReaderImpl(decrypter, mac, macKey);
|
return new ConnectionReaderImpl(decrypter, mac, macKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,9 @@ DatabaseListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void calculateIvs(ContactId c) throws DbException {
|
private synchronized void calculateIvs(ContactId c) throws DbException {
|
||||||
ErasableKey ivKey = crypto.deriveIncomingIvKey(db.getSharedSecret(c));
|
byte[] secret = db.getSharedSecret(c, true);
|
||||||
|
ErasableKey ivKey = crypto.deriveIvKey(secret, true);
|
||||||
|
for(int i = 0; i < secret.length; i++) secret[i] = 0;
|
||||||
for(TransportId t : localTransportIds) {
|
for(TransportId t : localTransportIds) {
|
||||||
TransportIndex i = db.getRemoteIndex(c, t);
|
TransportIndex i = db.getRemoteIndex(c, t);
|
||||||
if(i != null) {
|
if(i != null) {
|
||||||
@@ -131,7 +133,9 @@ DatabaseListener {
|
|||||||
TransportIndex i1 = ctx1.getTransportIndex();
|
TransportIndex i1 = ctx1.getTransportIndex();
|
||||||
if(c1.equals(c) && i1.equals(i)) it.remove();
|
if(c1.equals(c) && i1.equals(i)) it.remove();
|
||||||
}
|
}
|
||||||
ErasableKey ivKey = crypto.deriveIncomingIvKey(db.getSharedSecret(c));
|
byte[] secret = db.getSharedSecret(c, true);
|
||||||
|
ErasableKey ivKey = crypto.deriveIvKey(secret, true);
|
||||||
|
for(int j = 0; j < secret.length; j++) secret[j] = 0;
|
||||||
calculateIvs(c, ctx.getTransportId(), i, ivKey, w);
|
calculateIvs(c, ctx.getTransportId(), i, ivKey, w);
|
||||||
} catch(NoSuchContactException e) {
|
} catch(NoSuchContactException e) {
|
||||||
// The contact was removed - clean up when we get the event
|
// The contact was removed - clean up when we get the event
|
||||||
@@ -181,8 +185,9 @@ DatabaseListener {
|
|||||||
private synchronized void calculateIvs(TransportId t) throws DbException {
|
private synchronized void calculateIvs(TransportId t) throws DbException {
|
||||||
for(ContactId c : db.getContacts()) {
|
for(ContactId c : db.getContacts()) {
|
||||||
try {
|
try {
|
||||||
byte[] secret = db.getSharedSecret(c);
|
byte[] secret = db.getSharedSecret(c, true);
|
||||||
ErasableKey ivKey = crypto.deriveIncomingIvKey(secret);
|
ErasableKey ivKey = crypto.deriveIvKey(secret, true);
|
||||||
|
for(int i = 0; i < secret.length; i++) secret[i] = 0;
|
||||||
TransportIndex i = db.getRemoteIndex(c, t);
|
TransportIndex i = db.getRemoteIndex(c, t);
|
||||||
if(i != null) {
|
if(i != null) {
|
||||||
ConnectionWindow w = db.getConnectionWindow(c, i);
|
ConnectionWindow w = db.getConnectionWindow(c, i);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
|
|||||||
byte[] secret) {
|
byte[] secret) {
|
||||||
// Decrypt the IV
|
// Decrypt the IV
|
||||||
Cipher ivCipher = crypto.getIvCipher();
|
Cipher ivCipher = crypto.getIvCipher();
|
||||||
ErasableKey ivKey = crypto.deriveIncomingIvKey(secret);
|
ErasableKey ivKey = crypto.deriveIvKey(secret, true);
|
||||||
byte[] iv;
|
byte[] iv;
|
||||||
try {
|
try {
|
||||||
ivCipher.init(Cipher.DECRYPT_MODE, ivKey);
|
ivCipher.init(Cipher.DECRYPT_MODE, ivKey);
|
||||||
@@ -60,17 +60,19 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
|
|||||||
private ConnectionWriter createConnectionWriter(OutputStream out,
|
private ConnectionWriter createConnectionWriter(OutputStream out,
|
||||||
long capacity, boolean initiator, TransportIndex i, long connection,
|
long capacity, boolean initiator, TransportIndex i, long connection,
|
||||||
byte[] secret) {
|
byte[] secret) {
|
||||||
|
// Derive the keys and erase the secret
|
||||||
|
ErasableKey ivKey = crypto.deriveIvKey(secret, initiator);
|
||||||
|
ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator);
|
||||||
|
ErasableKey macKey = crypto.deriveMacKey(secret, initiator);
|
||||||
|
for(int j = 0; j < secret.length; j++) secret[j] = 0;
|
||||||
// Create the encrypter
|
// Create the encrypter
|
||||||
Cipher ivCipher = crypto.getIvCipher();
|
Cipher ivCipher = crypto.getIvCipher();
|
||||||
Cipher frameCipher = crypto.getFrameCipher();
|
Cipher frameCipher = crypto.getFrameCipher();
|
||||||
ErasableKey ivKey = crypto.deriveOutgoingIvKey(secret);
|
|
||||||
ErasableKey frameKey = crypto.deriveOutgoingFrameKey(secret);
|
|
||||||
byte[] iv = IvEncoder.encodeIv(initiator, i, connection);
|
byte[] iv = IvEncoder.encodeIv(initiator, i, connection);
|
||||||
ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out,
|
ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out,
|
||||||
capacity, iv, ivCipher, frameCipher, ivKey, frameKey);
|
capacity, iv, ivCipher, frameCipher, ivKey, frameKey);
|
||||||
// Create the writer
|
// Create the writer
|
||||||
Mac mac = crypto.getMac();
|
Mac mac = crypto.getMac();
|
||||||
ErasableKey macKey = crypto.deriveOutgoingMacKey(secret);
|
|
||||||
return new ConnectionWriterImpl(encrypter, mac, macKey);
|
return new ConnectionWriterImpl(encrypter, mac, macKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class IncomingBatchConnection {
|
|||||||
|
|
||||||
void read() {
|
void read() {
|
||||||
try {
|
try {
|
||||||
byte[] secret = db.getSharedSecret(contactId);
|
byte[] secret = db.getSharedSecret(contactId, true);
|
||||||
ConnectionReader conn = connFactory.createConnectionReader(
|
ConnectionReader conn = connFactory.createConnectionReader(
|
||||||
reader.getInputStream(), transportIndex, encryptedIv,
|
reader.getInputStream(), transportIndex, encryptedIv,
|
||||||
secret);
|
secret);
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class OutgoingBatchConnection {
|
|||||||
|
|
||||||
void write() {
|
void write() {
|
||||||
try {
|
try {
|
||||||
byte[] secret = db.getSharedSecret(contactId);
|
byte[] secret = db.getSharedSecret(contactId, false);
|
||||||
long connection = db.getConnectionNumber(contactId, transportIndex);
|
long connection = db.getConnectionNumber(contactId, transportIndex);
|
||||||
ConnectionWriter conn = connFactory.createConnectionWriter(
|
ConnectionWriter conn = connFactory.createConnectionWriter(
|
||||||
writer.getOutputStream(), writer.getCapacity(),
|
writer.getOutputStream(), writer.getCapacity(),
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class IncomingStreamConnection extends StreamConnection {
|
|||||||
@Override
|
@Override
|
||||||
protected ConnectionReader createConnectionReader() throws DbException,
|
protected ConnectionReader createConnectionReader() throws DbException,
|
||||||
IOException {
|
IOException {
|
||||||
byte[] secret = db.getSharedSecret(contactId);
|
byte[] secret = db.getSharedSecret(contactId, true);
|
||||||
return connReaderFactory.createConnectionReader(
|
return connReaderFactory.createConnectionReader(
|
||||||
connection.getInputStream(), transportIndex, encryptedIv,
|
connection.getInputStream(), transportIndex, encryptedIv,
|
||||||
secret);
|
secret);
|
||||||
@@ -42,7 +42,7 @@ public class IncomingStreamConnection extends StreamConnection {
|
|||||||
@Override
|
@Override
|
||||||
protected ConnectionWriter createConnectionWriter() throws DbException,
|
protected ConnectionWriter createConnectionWriter() throws DbException,
|
||||||
IOException {
|
IOException {
|
||||||
byte[] secret = db.getSharedSecret(contactId);
|
byte[] secret = db.getSharedSecret(contactId, false);
|
||||||
return connWriterFactory.createConnectionWriter(
|
return connWriterFactory.createConnectionWriter(
|
||||||
connection.getOutputStream(), Long.MAX_VALUE, transportIndex,
|
connection.getOutputStream(), Long.MAX_VALUE, transportIndex,
|
||||||
encryptedIv, secret);
|
encryptedIv, secret);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class OutgoingStreamConnection extends StreamConnection {
|
|||||||
transportIndex);
|
transportIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
byte[] secret = db.getSharedSecret(contactId);
|
byte[] secret = db.getSharedSecret(contactId, true);
|
||||||
return connReaderFactory.createConnectionReader(
|
return connReaderFactory.createConnectionReader(
|
||||||
connection.getInputStream(), transportIndex, connectionNum,
|
connection.getInputStream(), transportIndex, connectionNum,
|
||||||
secret);
|
secret);
|
||||||
@@ -52,7 +52,7 @@ public class OutgoingStreamConnection extends StreamConnection {
|
|||||||
transportIndex);
|
transportIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
byte[] secret = db.getSharedSecret(contactId);
|
byte[] secret = db.getSharedSecret(contactId, false);
|
||||||
return connWriterFactory.createConnectionWriter(
|
return connWriterFactory.createConnectionWriter(
|
||||||
connection.getOutputStream(), Long.MAX_VALUE, transportIndex,
|
connection.getOutputStream(), Long.MAX_VALUE, transportIndex,
|
||||||
connectionNum, secret);
|
connectionNum, secret);
|
||||||
|
|||||||
@@ -17,8 +17,6 @@
|
|||||||
<test name='net.sf.briar.LockFairnessTest'/>
|
<test name='net.sf.briar.LockFairnessTest'/>
|
||||||
<test name='net.sf.briar.ProtocolIntegrationTest'/>
|
<test name='net.sf.briar.ProtocolIntegrationTest'/>
|
||||||
<test name='net.sf.briar.crypto.CounterModeTest'/>
|
<test name='net.sf.briar.crypto.CounterModeTest'/>
|
||||||
<test name='net.sf.briar.crypto.CryptoComponentTest'/>
|
|
||||||
<test name='net.sf.briar.crypto.SharedSecretTest'/>
|
|
||||||
<test name='net.sf.briar.db.BasicH2Test'/>
|
<test name='net.sf.briar.db.BasicH2Test'/>
|
||||||
<test name='net.sf.briar.db.DatabaseCleanerImplTest'/>
|
<test name='net.sf.briar.db.DatabaseCleanerImplTest'/>
|
||||||
<test name='net.sf.briar.db.DatabaseComponentImplTest'/>
|
<test name='net.sf.briar.db.DatabaseComponentImplTest'/>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import java.util.Collections;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import net.sf.briar.api.crypto.CryptoComponent;
|
import net.sf.briar.api.crypto.CryptoComponent;
|
||||||
@@ -56,6 +57,7 @@ import net.sf.briar.transport.TransportModule;
|
|||||||
import net.sf.briar.transport.batch.TransportBatchModule;
|
import net.sf.briar.transport.batch.TransportBatchModule;
|
||||||
import net.sf.briar.transport.stream.TransportStreamModule;
|
import net.sf.briar.transport.stream.TransportStreamModule;
|
||||||
|
|
||||||
|
import org.bouncycastle.util.Arrays;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
@@ -71,7 +73,7 @@ public class ProtocolIntegrationTest extends TestCase {
|
|||||||
private final ProtocolReaderFactory protocolReaderFactory;
|
private final ProtocolReaderFactory protocolReaderFactory;
|
||||||
private final ProtocolWriterFactory protocolWriterFactory;
|
private final ProtocolWriterFactory protocolWriterFactory;
|
||||||
private final CryptoComponent crypto;
|
private final CryptoComponent crypto;
|
||||||
private final byte[] aliceSecret, bobSecret;
|
private final byte[] aliceToBobSecret;
|
||||||
private final TransportIndex transportIndex = new TransportIndex(13);
|
private final TransportIndex transportIndex = new TransportIndex(13);
|
||||||
private final long connection = 12345L;
|
private final long connection = 12345L;
|
||||||
private final Author author;
|
private final Author author;
|
||||||
@@ -96,10 +98,9 @@ public class ProtocolIntegrationTest extends TestCase {
|
|||||||
crypto = i.getInstance(CryptoComponent.class);
|
crypto = i.getInstance(CryptoComponent.class);
|
||||||
assertEquals(crypto.getMessageDigest().getDigestLength(),
|
assertEquals(crypto.getMessageDigest().getDigestLength(),
|
||||||
UniqueId.LENGTH);
|
UniqueId.LENGTH);
|
||||||
// Create matching secrets: one for Alice, one for Bob
|
Random r = new Random();
|
||||||
aliceSecret = new byte[123];
|
aliceToBobSecret = new byte[123];
|
||||||
aliceSecret[0] = (byte) 1;
|
r.nextBytes(aliceToBobSecret);
|
||||||
bobSecret = new byte[123];
|
|
||||||
// Create two groups: one restricted, one unrestricted
|
// Create two groups: one restricted, one unrestricted
|
||||||
GroupFactory groupFactory = i.getInstance(GroupFactory.class);
|
GroupFactory groupFactory = i.getInstance(GroupFactory.class);
|
||||||
group = groupFactory.createGroup("Unrestricted group", null);
|
group = groupFactory.createGroup("Unrestricted group", null);
|
||||||
@@ -138,9 +139,9 @@ public class ProtocolIntegrationTest extends TestCase {
|
|||||||
|
|
||||||
private byte[] write() throws Exception {
|
private byte[] write() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
// Use Alice's secret for writing
|
byte[] copyOfSecret = Arrays.clone(aliceToBobSecret);
|
||||||
ConnectionWriter w = connectionWriterFactory.createConnectionWriter(out,
|
ConnectionWriter w = connectionWriterFactory.createConnectionWriter(out,
|
||||||
Long.MAX_VALUE, transportIndex, connection, aliceSecret);
|
Long.MAX_VALUE, transportIndex, connection, copyOfSecret);
|
||||||
OutputStream out1 = w.getOutputStream();
|
OutputStream out1 = w.getOutputStream();
|
||||||
|
|
||||||
AckWriter a = protocolWriterFactory.createAckWriter(out1);
|
AckWriter a = protocolWriterFactory.createAckWriter(out1);
|
||||||
@@ -193,9 +194,9 @@ public class ProtocolIntegrationTest extends TestCase {
|
|||||||
offset += read;
|
offset += read;
|
||||||
}
|
}
|
||||||
assertEquals(16, offset);
|
assertEquals(16, offset);
|
||||||
// Use Bob's secret for reading
|
byte[] copyOfSecret = Arrays.clone(aliceToBobSecret);
|
||||||
ConnectionReader r = connectionReaderFactory.createConnectionReader(in,
|
ConnectionReader r = connectionReaderFactory.createConnectionReader(in,
|
||||||
transportIndex, encryptedIv, bobSecret);
|
transportIndex, encryptedIv, copyOfSecret);
|
||||||
in = r.getInputStream();
|
in = r.getInputStream();
|
||||||
ProtocolReader protocolReader =
|
ProtocolReader protocolReader =
|
||||||
protocolReaderFactory.createProtocolReader(in);
|
protocolReaderFactory.createProtocolReader(in);
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
package net.sf.briar.crypto;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
import net.sf.briar.api.crypto.CryptoComponent;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import com.google.inject.Guice;
|
|
||||||
import com.google.inject.Injector;
|
|
||||||
|
|
||||||
public class CryptoComponentTest extends TestCase {
|
|
||||||
|
|
||||||
private final CryptoComponent crypto;
|
|
||||||
|
|
||||||
public CryptoComponentTest() {
|
|
||||||
super();
|
|
||||||
Injector i = Guice.createInjector(new CryptoModule());
|
|
||||||
crypto = i.getInstance(CryptoComponent.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testKeyDerivation() {
|
|
||||||
// Create matching secrets: one for Alice, one for Bob
|
|
||||||
byte[] aliceSecret = new byte[123];
|
|
||||||
aliceSecret[0] = (byte) 1;
|
|
||||||
byte[] bobSecret = new byte[123];
|
|
||||||
// Check that Alice's incoming keys match Bob's outgoing keys
|
|
||||||
assertEquals(crypto.deriveIncomingMacKey(aliceSecret),
|
|
||||||
crypto.deriveOutgoingMacKey(bobSecret));
|
|
||||||
assertEquals(crypto.deriveIncomingFrameKey(aliceSecret),
|
|
||||||
crypto.deriveOutgoingFrameKey(bobSecret));
|
|
||||||
assertEquals(crypto.deriveIncomingIvKey(aliceSecret),
|
|
||||||
crypto.deriveOutgoingIvKey(bobSecret));
|
|
||||||
// Check that Alice's outgoing keys match Bob's incoming keys
|
|
||||||
assertEquals(crypto.deriveOutgoingMacKey(aliceSecret),
|
|
||||||
crypto.deriveIncomingMacKey(bobSecret));
|
|
||||||
assertEquals(crypto.deriveOutgoingFrameKey(aliceSecret),
|
|
||||||
crypto.deriveIncomingFrameKey(bobSecret));
|
|
||||||
assertEquals(crypto.deriveOutgoingIvKey(aliceSecret),
|
|
||||||
crypto.deriveIncomingIvKey(bobSecret));
|
|
||||||
// Check that Alice's incoming and outgoing keys are different
|
|
||||||
assertFalse(crypto.deriveIncomingMacKey(aliceSecret).equals(
|
|
||||||
crypto.deriveOutgoingMacKey(aliceSecret)));
|
|
||||||
assertFalse(crypto.deriveIncomingFrameKey(aliceSecret).equals(
|
|
||||||
crypto.deriveOutgoingFrameKey(aliceSecret)));
|
|
||||||
assertFalse(crypto.deriveIncomingIvKey(aliceSecret).equals(
|
|
||||||
crypto.deriveOutgoingIvKey(aliceSecret)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package net.sf.briar.crypto;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class SharedSecretTest extends TestCase {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDecodeAndEncode() {
|
|
||||||
Random random = new Random();
|
|
||||||
byte[] secret = new byte[40];
|
|
||||||
random.nextBytes(secret);
|
|
||||||
secret[0] = (byte) 0;
|
|
||||||
SharedSecret s = new SharedSecret(secret);
|
|
||||||
assertArrayEquals(secret, s.getBytes());
|
|
||||||
secret[0] = (byte) 1;
|
|
||||||
s = new SharedSecret(secret);
|
|
||||||
assertArrayEquals(secret, s.getBytes());
|
|
||||||
// The Alice flag must be either 0 or 1
|
|
||||||
secret[0] = (byte) 2;
|
|
||||||
try {
|
|
||||||
s = new SharedSecret(secret);
|
|
||||||
fail();
|
|
||||||
} catch(IllegalArgumentException expected) {}
|
|
||||||
// The secret must be at least 1 byte long
|
|
||||||
secret = new byte[1];
|
|
||||||
random.nextBytes(secret);
|
|
||||||
secret[0] = (byte) 0;
|
|
||||||
try {
|
|
||||||
s = new SharedSecret(secret);
|
|
||||||
fail();
|
|
||||||
} catch(IllegalArgumentException expected) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,6 +5,7 @@ import java.util.BitSet;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import net.sf.briar.TestUtils;
|
import net.sf.briar.TestUtils;
|
||||||
@@ -46,6 +47,7 @@ import net.sf.briar.api.transport.ConnectionWindow;
|
|||||||
|
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.jmock.Mockery;
|
import org.jmock.Mockery;
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public abstract class DatabaseComponentTest extends TestCase {
|
public abstract class DatabaseComponentTest extends TestCase {
|
||||||
@@ -66,7 +68,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
private final TransportIndex localIndex, remoteIndex;
|
private final TransportIndex localIndex, remoteIndex;
|
||||||
private final Collection<Transport> transports;
|
private final Collection<Transport> transports;
|
||||||
private final Map<ContactId, TransportProperties> remoteProperties;
|
private final Map<ContactId, TransportProperties> remoteProperties;
|
||||||
private final byte[] secret;
|
private final byte[] inSecret, outSecret;
|
||||||
|
|
||||||
public DatabaseComponentTest() {
|
public DatabaseComponentTest() {
|
||||||
super();
|
super();
|
||||||
@@ -94,7 +96,11 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
Transport transport = new Transport(transportId, localIndex,
|
Transport transport = new Transport(transportId, localIndex,
|
||||||
properties);
|
properties);
|
||||||
transports = Collections.singletonList(transport);
|
transports = Collections.singletonList(transport);
|
||||||
secret = new byte[123];
|
Random r = new Random();
|
||||||
|
inSecret = new byte[123];
|
||||||
|
r.nextBytes(inSecret);
|
||||||
|
outSecret = new byte[123];
|
||||||
|
r.nextBytes(outSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract <T> DatabaseComponent createDatabaseComponent(
|
protected abstract <T> DatabaseComponent createDatabaseComponent(
|
||||||
@@ -132,7 +138,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
oneOf(database).setRating(txn, authorId, Rating.GOOD);
|
oneOf(database).setRating(txn, authorId, Rating.GOOD);
|
||||||
will(returnValue(Rating.GOOD));
|
will(returnValue(Rating.GOOD));
|
||||||
// addContact()
|
// addContact()
|
||||||
oneOf(database).addContact(txn, secret);
|
oneOf(database).addContact(txn, inSecret, outSecret);
|
||||||
will(returnValue(contactId));
|
will(returnValue(contactId));
|
||||||
oneOf(listener).eventOccurred(with(any(ContactAddedEvent.class)));
|
oneOf(listener).eventOccurred(with(any(ContactAddedEvent.class)));
|
||||||
// getContacts()
|
// getContacts()
|
||||||
@@ -143,11 +149,16 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).getConnectionWindow(txn, contactId, remoteIndex);
|
oneOf(database).getConnectionWindow(txn, contactId, remoteIndex);
|
||||||
will(returnValue(connectionWindow));
|
will(returnValue(connectionWindow));
|
||||||
// getSharedSecret(contactId)
|
// getSharedSecret(contactId, true)
|
||||||
oneOf(database).containsContact(txn, contactId);
|
oneOf(database).containsContact(txn, contactId);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).getSharedSecret(txn, contactId);
|
oneOf(database).getSharedSecret(txn, contactId, true);
|
||||||
will(returnValue(secret));
|
will(returnValue(inSecret));
|
||||||
|
// getSharedSecret(contactId, false)
|
||||||
|
oneOf(database).containsContact(txn, contactId);
|
||||||
|
will(returnValue(true));
|
||||||
|
oneOf(database).getSharedSecret(txn, contactId, false);
|
||||||
|
will(returnValue(outSecret));
|
||||||
// getTransportProperties(transportId)
|
// getTransportProperties(transportId)
|
||||||
oneOf(database).getRemoteProperties(txn, transportId);
|
oneOf(database).getRemoteProperties(txn, transportId);
|
||||||
will(returnValue(remoteProperties));
|
will(returnValue(remoteProperties));
|
||||||
@@ -198,11 +209,12 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
assertEquals(Rating.UNRATED, db.getRating(authorId));
|
assertEquals(Rating.UNRATED, db.getRating(authorId));
|
||||||
db.setRating(authorId, Rating.GOOD); // First time - listeners called
|
db.setRating(authorId, Rating.GOOD); // First time - listeners called
|
||||||
db.setRating(authorId, Rating.GOOD); // Second time - not called
|
db.setRating(authorId, Rating.GOOD); // Second time - not called
|
||||||
assertEquals(contactId, db.addContact(secret));
|
assertEquals(contactId, db.addContact(inSecret, outSecret));
|
||||||
assertEquals(Collections.singletonList(contactId), db.getContacts());
|
assertEquals(Collections.singletonList(contactId), db.getContacts());
|
||||||
assertEquals(connectionWindow,
|
assertEquals(connectionWindow,
|
||||||
db.getConnectionWindow(contactId, remoteIndex));
|
db.getConnectionWindow(contactId, remoteIndex));
|
||||||
assertEquals(secret, db.getSharedSecret(contactId));
|
assertArrayEquals(inSecret, db.getSharedSecret(contactId, true));
|
||||||
|
assertArrayEquals(outSecret, db.getSharedSecret(contactId, false));
|
||||||
assertEquals(remoteProperties, db.getRemoteProperties(transportId));
|
assertEquals(remoteProperties, db.getRemoteProperties(transportId));
|
||||||
db.subscribe(group); // First time - listeners called
|
db.subscribe(group); // First time - listeners called
|
||||||
db.subscribe(group); // Second time - not called
|
db.subscribe(group); // Second time - not called
|
||||||
@@ -564,7 +576,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
} catch(NoSuchContactException expected) {}
|
} catch(NoSuchContactException expected) {}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
db.getSharedSecret(contactId);
|
db.getSharedSecret(contactId, true);
|
||||||
fail();
|
fail();
|
||||||
} catch(NoSuchContactException expected) {}
|
} catch(NoSuchContactException expected) {}
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
private final Map<ContactId, TransportProperties> remoteProperties;
|
private final Map<ContactId, TransportProperties> remoteProperties;
|
||||||
private final Collection<Transport> remoteTransports;
|
private final Collection<Transport> remoteTransports;
|
||||||
private final Map<Group, Long> subscriptions;
|
private final Map<Group, Long> subscriptions;
|
||||||
private final byte[] secret;
|
private final byte[] inSecret, outSecret;
|
||||||
|
|
||||||
public H2DatabaseTest() throws Exception {
|
public H2DatabaseTest() throws Exception {
|
||||||
super();
|
super();
|
||||||
@@ -122,7 +122,11 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
properties);
|
properties);
|
||||||
remoteTransports = Collections.singletonList(remoteTransport);
|
remoteTransports = Collections.singletonList(remoteTransport);
|
||||||
subscriptions = Collections.singletonMap(group, 0L);
|
subscriptions = Collections.singletonMap(group, 0L);
|
||||||
secret = new byte[123];
|
Random r = new Random();
|
||||||
|
inSecret = new byte[123];
|
||||||
|
r.nextBytes(inSecret);
|
||||||
|
outSecret = new byte[123];
|
||||||
|
r.nextBytes(outSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -136,7 +140,8 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
assertFalse(db.containsContact(txn, contactId));
|
assertFalse(db.containsContact(txn, contactId));
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId,
|
||||||
|
db.addContact(txn, inSecret, outSecret));
|
||||||
assertTrue(db.containsContact(txn, contactId));
|
assertTrue(db.containsContact(txn, contactId));
|
||||||
assertFalse(db.containsSubscription(txn, groupId));
|
assertFalse(db.containsSubscription(txn, groupId));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
@@ -192,20 +197,20 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
|
|
||||||
// Create three contacts
|
// Create three contacts
|
||||||
assertFalse(db.containsContact(txn, contactId));
|
assertFalse(db.containsContact(txn, contactId));
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
assertTrue(db.containsContact(txn, contactId));
|
assertTrue(db.containsContact(txn, contactId));
|
||||||
assertFalse(db.containsContact(txn, contactId1));
|
assertFalse(db.containsContact(txn, contactId1));
|
||||||
assertEquals(contactId1, db.addContact(txn, secret));
|
assertEquals(contactId1, db.addContact(txn, inSecret, outSecret));
|
||||||
assertTrue(db.containsContact(txn, contactId1));
|
assertTrue(db.containsContact(txn, contactId1));
|
||||||
assertFalse(db.containsContact(txn, contactId2));
|
assertFalse(db.containsContact(txn, contactId2));
|
||||||
assertEquals(contactId2, db.addContact(txn, secret));
|
assertEquals(contactId2, db.addContact(txn, inSecret, outSecret));
|
||||||
assertTrue(db.containsContact(txn, contactId2));
|
assertTrue(db.containsContact(txn, contactId2));
|
||||||
// Delete the contact with the highest ID
|
// Delete the contact with the highest ID
|
||||||
db.removeContact(txn, contactId2);
|
db.removeContact(txn, contactId2);
|
||||||
assertFalse(db.containsContact(txn, contactId2));
|
assertFalse(db.containsContact(txn, contactId2));
|
||||||
// Add another contact - a new ID should be created
|
// Add another contact - a new ID should be created
|
||||||
assertFalse(db.containsContact(txn, contactId3));
|
assertFalse(db.containsContact(txn, contactId3));
|
||||||
assertEquals(contactId3, db.addContact(txn, secret));
|
assertEquals(contactId3, db.addContact(txn, inSecret, outSecret));
|
||||||
assertTrue(db.containsContact(txn, contactId3));
|
assertTrue(db.containsContact(txn, contactId3));
|
||||||
|
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
@@ -252,7 +257,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact and store a private message
|
// Add a contact and store a private message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addPrivateMessage(txn, privateMessage, contactId);
|
db.addPrivateMessage(txn, privateMessage, contactId);
|
||||||
|
|
||||||
// Removing the contact should remove the message
|
// Removing the contact should remove the message
|
||||||
@@ -271,7 +276,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact and store a private message
|
// Add a contact and store a private message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addPrivateMessage(txn, privateMessage, contactId);
|
db.addPrivateMessage(txn, privateMessage, contactId);
|
||||||
|
|
||||||
// The message has no status yet, so it should not be sendable
|
// The message has no status yet, so it should not be sendable
|
||||||
@@ -310,7 +315,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact and store a private message
|
// Add a contact and store a private message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addPrivateMessage(txn, privateMessage, contactId);
|
db.addPrivateMessage(txn, privateMessage, contactId);
|
||||||
db.setStatus(txn, contactId, privateMessageId, Status.NEW);
|
db.setStatus(txn, contactId, privateMessageId, Status.NEW);
|
||||||
|
|
||||||
@@ -338,7 +343,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
@@ -376,7 +381,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
@@ -418,7 +423,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
||||||
db.addGroupMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
@@ -457,7 +462,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
||||||
db.addGroupMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
@@ -492,7 +497,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
@@ -523,7 +528,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
db.addGroupMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
@@ -556,7 +561,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact and some batches to ack
|
// Add a contact and some batches to ack
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addBatchToAck(txn, contactId, batchId);
|
db.addBatchToAck(txn, contactId, batchId);
|
||||||
db.addBatchToAck(txn, contactId, batchId1);
|
db.addBatchToAck(txn, contactId, batchId1);
|
||||||
|
|
||||||
@@ -583,7 +588,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact and receive the same batch twice
|
// Add a contact and receive the same batch twice
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addBatchToAck(txn, contactId, batchId);
|
db.addBatchToAck(txn, contactId, batchId);
|
||||||
db.addBatchToAck(txn, contactId, batchId);
|
db.addBatchToAck(txn, contactId, batchId);
|
||||||
|
|
||||||
@@ -609,7 +614,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.addGroupMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
|
|
||||||
@@ -634,8 +639,8 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add two contacts, subscribe to a group and store a message
|
// Add two contacts, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
ContactId contactId1 = db.addContact(txn, secret);
|
ContactId contactId1 = db.addContact(txn, inSecret, outSecret);
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.addGroupMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
|
|
||||||
@@ -657,7 +662,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
@@ -696,7 +701,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
@@ -741,7 +746,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact
|
// Add a contact
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
|
|
||||||
// Add some outstanding batches, a few ms apart
|
// Add some outstanding batches, a few ms apart
|
||||||
for(int i = 0; i < ids.length; i++) {
|
for(int i = 0; i < ids.length; i++) {
|
||||||
@@ -781,7 +786,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact
|
// Add a contact
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
|
|
||||||
// Add some outstanding batches, a few ms apart
|
// Add some outstanding batches, a few ms apart
|
||||||
for(int i = 0; i < ids.length; i++) {
|
for(int i = 0; i < ids.length; i++) {
|
||||||
@@ -1001,7 +1006,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact with a transport
|
// Add a contact with a transport
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.setTransports(txn, contactId, remoteTransports, 1);
|
db.setTransports(txn, contactId, remoteTransports, 1);
|
||||||
assertEquals(remoteProperties,
|
assertEquals(remoteProperties,
|
||||||
db.getRemoteProperties(txn, transportId));
|
db.getRemoteProperties(txn, transportId));
|
||||||
@@ -1094,7 +1099,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact with a transport
|
// Add a contact with a transport
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.setTransports(txn, contactId, remoteTransports, 1);
|
db.setTransports(txn, contactId, remoteTransports, 1);
|
||||||
assertEquals(remoteProperties,
|
assertEquals(remoteProperties,
|
||||||
db.getRemoteProperties(txn, transportId));
|
db.getRemoteProperties(txn, transportId));
|
||||||
@@ -1138,7 +1143,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact with some subscriptions
|
// Add a contact with some subscriptions
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
assertEquals(Collections.singletonList(group),
|
assertEquals(Collections.singletonList(group),
|
||||||
db.getSubscriptions(txn, contactId));
|
db.getSubscriptions(txn, contactId));
|
||||||
@@ -1163,7 +1168,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact with some subscriptions
|
// Add a contact with some subscriptions
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 2);
|
db.setSubscriptions(txn, contactId, subscriptions, 2);
|
||||||
assertEquals(Collections.singletonList(group),
|
assertEquals(Collections.singletonList(group),
|
||||||
db.getSubscriptions(txn, contactId));
|
db.getSubscriptions(txn, contactId));
|
||||||
@@ -1187,7 +1192,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact and subscribe to a group
|
// Add a contact and subscribe to a group
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
|
|
||||||
@@ -1205,7 +1210,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
db.addGroupMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
@@ -1228,7 +1233,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
db.addGroupMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
@@ -1251,7 +1256,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message -
|
// Add a contact, subscribe to a group and store a message -
|
||||||
// the message is older than the contact's subscription
|
// the message is older than the contact's subscription
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
||||||
Map<Group, Long> subs = Collections.singletonMap(group, timestamp + 1);
|
Map<Group, Long> subs = Collections.singletonMap(group, timestamp + 1);
|
||||||
@@ -1275,7 +1280,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
@@ -1300,7 +1305,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact and subscribe to a group
|
// Add a contact and subscribe to a group
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
@@ -1319,7 +1324,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact with a subscription
|
// Add a contact with a subscription
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
|
|
||||||
// There's no local subscription for the group
|
// There's no local subscription for the group
|
||||||
@@ -1336,7 +1341,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.addGroupMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
db.setStatus(txn, contactId, messageId, Status.NEW);
|
db.setStatus(txn, contactId, messageId, Status.NEW);
|
||||||
@@ -1355,7 +1360,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.addGroupMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
@@ -1375,7 +1380,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
@@ -1397,7 +1402,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
db.setVisibility(txn, groupId, Collections.singletonList(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
@@ -1418,7 +1423,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact and subscribe to a group
|
// Add a contact and subscribe to a group
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
// The group should not be visible to the contact
|
// The group should not be visible to the contact
|
||||||
assertEquals(Collections.emptyList(), db.getVisibility(txn, groupId));
|
assertEquals(Collections.emptyList(), db.getVisibility(txn, groupId));
|
||||||
@@ -1441,7 +1446,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact
|
// Add a contact
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
// Get the connection window for a new index
|
// Get the connection window for a new index
|
||||||
ConnectionWindow w = db.getConnectionWindow(txn, contactId,
|
ConnectionWindow w = db.getConnectionWindow(txn, contactId,
|
||||||
remoteIndex);
|
remoteIndex);
|
||||||
@@ -1460,7 +1465,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact
|
// Add a contact
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
// Get the connection window for a new index
|
// Get the connection window for a new index
|
||||||
ConnectionWindow w = db.getConnectionWindow(txn, contactId,
|
ConnectionWindow w = db.getConnectionWindow(txn, contactId,
|
||||||
remoteIndex);
|
remoteIndex);
|
||||||
@@ -1564,7 +1569,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact and subscribe to a group
|
// Add a contact and subscribe to a group
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
|
|
||||||
// A message with a private parent should return null
|
// A message with a private parent should return null
|
||||||
@@ -1613,7 +1618,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact
|
// Add a contact
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
|
|
||||||
// The subscription and transport timestamps should be initialised to 0
|
// The subscription and transport timestamps should be initialised to 0
|
||||||
assertEquals(0L, db.getSubscriptionsModified(txn, contactId));
|
assertEquals(0L, db.getSubscriptionsModified(txn, contactId));
|
||||||
@@ -1644,7 +1649,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact and subscribe to a group
|
// Add a contact and subscribe to a group
|
||||||
assertEquals(contactId, db.addContact(txn, secret));
|
assertEquals(contactId, db.addContact(txn, inSecret, outSecret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
|
|
||||||
// Store a couple of messages
|
// Store a couple of messages
|
||||||
|
|||||||
@@ -4,14 +4,15 @@ import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import net.sf.briar.api.crypto.ErasableKey;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import net.sf.briar.TestUtils;
|
import net.sf.briar.TestUtils;
|
||||||
import net.sf.briar.api.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
import net.sf.briar.api.crypto.CryptoComponent;
|
import net.sf.briar.api.crypto.CryptoComponent;
|
||||||
|
import net.sf.briar.api.crypto.ErasableKey;
|
||||||
import net.sf.briar.api.db.DatabaseComponent;
|
import net.sf.briar.api.db.DatabaseComponent;
|
||||||
import net.sf.briar.api.protocol.Transport;
|
import net.sf.briar.api.protocol.Transport;
|
||||||
import net.sf.briar.api.protocol.TransportId;
|
import net.sf.briar.api.protocol.TransportId;
|
||||||
@@ -31,7 +32,7 @@ public class ConnectionRecogniserImplTest extends TestCase {
|
|||||||
|
|
||||||
private final CryptoComponent crypto;
|
private final CryptoComponent crypto;
|
||||||
private final ContactId contactId;
|
private final ContactId contactId;
|
||||||
private final byte[] secret;
|
private final byte[] inSecret;
|
||||||
private final TransportId transportId;
|
private final TransportId transportId;
|
||||||
private final TransportIndex localIndex, remoteIndex;
|
private final TransportIndex localIndex, remoteIndex;
|
||||||
private final Collection<Transport> transports;
|
private final Collection<Transport> transports;
|
||||||
@@ -42,7 +43,8 @@ public class ConnectionRecogniserImplTest extends TestCase {
|
|||||||
Injector i = Guice.createInjector(new CryptoModule());
|
Injector i = Guice.createInjector(new CryptoModule());
|
||||||
crypto = i.getInstance(CryptoComponent.class);
|
crypto = i.getInstance(CryptoComponent.class);
|
||||||
contactId = new ContactId(1);
|
contactId = new ContactId(1);
|
||||||
secret = new byte[18];
|
inSecret = new byte[123];
|
||||||
|
new Random().nextBytes(inSecret);
|
||||||
transportId = new TransportId(TestUtils.getRandomId());
|
transportId = new TransportId(TestUtils.getRandomId());
|
||||||
localIndex = new TransportIndex(13);
|
localIndex = new TransportIndex(13);
|
||||||
remoteIndex = new TransportIndex(7);
|
remoteIndex = new TransportIndex(7);
|
||||||
@@ -63,8 +65,8 @@ public class ConnectionRecogniserImplTest extends TestCase {
|
|||||||
will(returnValue(transports));
|
will(returnValue(transports));
|
||||||
oneOf(db).getContacts();
|
oneOf(db).getContacts();
|
||||||
will(returnValue(Collections.singletonList(contactId)));
|
will(returnValue(Collections.singletonList(contactId)));
|
||||||
oneOf(db).getSharedSecret(contactId);
|
oneOf(db).getSharedSecret(contactId, true);
|
||||||
will(returnValue(secret));
|
will(returnValue(inSecret));
|
||||||
oneOf(db).getRemoteIndex(contactId, transportId);
|
oneOf(db).getRemoteIndex(contactId, transportId);
|
||||||
will(returnValue(remoteIndex));
|
will(returnValue(remoteIndex));
|
||||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||||
@@ -79,7 +81,7 @@ public class ConnectionRecogniserImplTest extends TestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testExpectedIv() throws Exception {
|
public void testExpectedIv() throws Exception {
|
||||||
// Calculate the expected IV for connection number 3
|
// Calculate the expected IV for connection number 3
|
||||||
ErasableKey ivKey = crypto.deriveIncomingIvKey(secret);
|
ErasableKey ivKey = crypto.deriveIvKey(inSecret, true);
|
||||||
Cipher ivCipher = crypto.getIvCipher();
|
Cipher ivCipher = crypto.getIvCipher();
|
||||||
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
||||||
byte[] iv = IvEncoder.encodeIv(true, remoteIndex, 3L);
|
byte[] iv = IvEncoder.encodeIv(true, remoteIndex, 3L);
|
||||||
@@ -94,8 +96,8 @@ public class ConnectionRecogniserImplTest extends TestCase {
|
|||||||
will(returnValue(transports));
|
will(returnValue(transports));
|
||||||
oneOf(db).getContacts();
|
oneOf(db).getContacts();
|
||||||
will(returnValue(Collections.singletonList(contactId)));
|
will(returnValue(Collections.singletonList(contactId)));
|
||||||
oneOf(db).getSharedSecret(contactId);
|
oneOf(db).getSharedSecret(contactId, true);
|
||||||
will(returnValue(secret));
|
will(returnValue(inSecret));
|
||||||
oneOf(db).getRemoteIndex(contactId, transportId);
|
oneOf(db).getRemoteIndex(contactId, transportId);
|
||||||
will(returnValue(remoteIndex));
|
will(returnValue(remoteIndex));
|
||||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||||
@@ -105,8 +107,8 @@ public class ConnectionRecogniserImplTest extends TestCase {
|
|||||||
will(returnValue(connectionWindow));
|
will(returnValue(connectionWindow));
|
||||||
oneOf(db).setConnectionWindow(contactId, remoteIndex,
|
oneOf(db).setConnectionWindow(contactId, remoteIndex,
|
||||||
connectionWindow);
|
connectionWindow);
|
||||||
oneOf(db).getSharedSecret(contactId);
|
oneOf(db).getSharedSecret(contactId, true);
|
||||||
will(returnValue(secret));
|
will(returnValue(inSecret));
|
||||||
}});
|
}});
|
||||||
final ConnectionRecogniserImpl c =
|
final ConnectionRecogniserImpl c =
|
||||||
new ConnectionRecogniserImpl(crypto, db);
|
new ConnectionRecogniserImpl(crypto, db);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PACKET_LENGTH;
|
|||||||
import static net.sf.briar.api.transport.TransportConstants.MIN_CONNECTION_LENGTH;
|
import static net.sf.briar.api.transport.TransportConstants.MIN_CONNECTION_LENGTH;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import net.sf.briar.TestDatabaseModule;
|
import net.sf.briar.TestDatabaseModule;
|
||||||
@@ -26,7 +27,7 @@ import com.google.inject.Injector;
|
|||||||
public class ConnectionWriterTest extends TestCase {
|
public class ConnectionWriterTest extends TestCase {
|
||||||
|
|
||||||
private final ConnectionWriterFactory connectionWriterFactory;
|
private final ConnectionWriterFactory connectionWriterFactory;
|
||||||
private final byte[] secret = new byte[100];
|
private final byte[] outSecret;
|
||||||
private final TransportIndex transportIndex = new TransportIndex(13);
|
private final TransportIndex transportIndex = new TransportIndex(13);
|
||||||
private final long connection = 12345L;
|
private final long connection = 12345L;
|
||||||
|
|
||||||
@@ -38,6 +39,8 @@ public class ConnectionWriterTest extends TestCase {
|
|||||||
new TestDatabaseModule(), new TransportBatchModule(),
|
new TestDatabaseModule(), new TransportBatchModule(),
|
||||||
new TransportModule(), new TransportStreamModule());
|
new TransportModule(), new TransportStreamModule());
|
||||||
connectionWriterFactory = i.getInstance(ConnectionWriterFactory.class);
|
connectionWriterFactory = i.getInstance(ConnectionWriterFactory.class);
|
||||||
|
outSecret = new byte[123];
|
||||||
|
new Random().nextBytes(outSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -45,7 +48,7 @@ public class ConnectionWriterTest extends TestCase {
|
|||||||
ByteArrayOutputStream out =
|
ByteArrayOutputStream out =
|
||||||
new ByteArrayOutputStream(MIN_CONNECTION_LENGTH);
|
new ByteArrayOutputStream(MIN_CONNECTION_LENGTH);
|
||||||
ConnectionWriter w = connectionWriterFactory.createConnectionWriter(out,
|
ConnectionWriter w = connectionWriterFactory.createConnectionWriter(out,
|
||||||
MIN_CONNECTION_LENGTH, transportIndex, connection, secret);
|
MIN_CONNECTION_LENGTH, transportIndex, connection, outSecret);
|
||||||
// Check that the connection writer thinks there's room for a packet
|
// Check that the connection writer thinks there's room for a packet
|
||||||
long capacity = w.getRemainingCapacity();
|
long capacity = w.getRemainingCapacity();
|
||||||
assertTrue(capacity >= MAX_PACKET_LENGTH);
|
assertTrue(capacity >= MAX_PACKET_LENGTH);
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ public class FrameReadWriteTest extends TestCase {
|
|||||||
|
|
||||||
private final CryptoComponent crypto;
|
private final CryptoComponent crypto;
|
||||||
private final Cipher ivCipher, frameCipher;
|
private final Cipher ivCipher, frameCipher;
|
||||||
|
private final Random random;
|
||||||
|
private final byte[] outSecret;
|
||||||
private final ErasableKey ivKey, frameKey, macKey;
|
private final ErasableKey ivKey, frameKey, macKey;
|
||||||
private final Mac mac;
|
private final Mac mac;
|
||||||
private final Random random;
|
|
||||||
private final byte[] secret = new byte[100];
|
|
||||||
private final TransportIndex transportIndex = new TransportIndex(13);
|
private final TransportIndex transportIndex = new TransportIndex(13);
|
||||||
private final long connection = 12345L;
|
private final long connection = 12345L;
|
||||||
|
|
||||||
@@ -42,12 +42,14 @@ public class FrameReadWriteTest extends TestCase {
|
|||||||
crypto = i.getInstance(CryptoComponent.class);
|
crypto = i.getInstance(CryptoComponent.class);
|
||||||
ivCipher = crypto.getIvCipher();
|
ivCipher = crypto.getIvCipher();
|
||||||
frameCipher = crypto.getFrameCipher();
|
frameCipher = crypto.getFrameCipher();
|
||||||
// Since we're sending frames to ourselves, we only need outgoing keys
|
|
||||||
ivKey = crypto.deriveOutgoingIvKey(secret);
|
|
||||||
frameKey = crypto.deriveOutgoingFrameKey(secret);
|
|
||||||
macKey = crypto.deriveOutgoingMacKey(secret);
|
|
||||||
mac = crypto.getMac();
|
|
||||||
random = new Random();
|
random = new Random();
|
||||||
|
// Since we're sending frames to ourselves, we only need outgoing keys
|
||||||
|
outSecret = new byte[123];
|
||||||
|
random.nextBytes(outSecret);
|
||||||
|
ivKey = crypto.deriveIvKey(outSecret, true);
|
||||||
|
frameKey = crypto.deriveFrameKey(outSecret, true);
|
||||||
|
macKey = crypto.deriveMacKey(outSecret, true);
|
||||||
|
mac = crypto.getMac();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.io.InputStream;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import net.sf.briar.TestDatabaseModule;
|
import net.sf.briar.TestDatabaseModule;
|
||||||
@@ -54,7 +55,7 @@ public class BatchConnectionReadWriteTest extends TestCase {
|
|||||||
private final File bobDir = new File(testDir, "bob");
|
private final File bobDir = new File(testDir, "bob");
|
||||||
private final TransportId transportId;
|
private final TransportId transportId;
|
||||||
private final TransportIndex transportIndex;
|
private final TransportIndex transportIndex;
|
||||||
private final byte[] aliceSecret, bobSecret;
|
private final byte[] aliceToBobSecret, bobToAliceSecret;
|
||||||
|
|
||||||
private Injector alice, bob;
|
private Injector alice, bob;
|
||||||
|
|
||||||
@@ -63,9 +64,11 @@ public class BatchConnectionReadWriteTest extends TestCase {
|
|||||||
transportId = new TransportId(TestUtils.getRandomId());
|
transportId = new TransportId(TestUtils.getRandomId());
|
||||||
transportIndex = new TransportIndex(1);
|
transportIndex = new TransportIndex(1);
|
||||||
// Create matching secrets for Alice and Bob
|
// Create matching secrets for Alice and Bob
|
||||||
aliceSecret = new byte[123];
|
Random r = new Random();
|
||||||
aliceSecret[0] = (byte) 1;
|
aliceToBobSecret = new byte[123];
|
||||||
bobSecret = new byte[123];
|
r.nextBytes(aliceToBobSecret);
|
||||||
|
bobToAliceSecret = new byte[123];
|
||||||
|
r.nextBytes(bobToAliceSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -102,7 +105,7 @@ public class BatchConnectionReadWriteTest extends TestCase {
|
|||||||
DatabaseComponent db = alice.getInstance(DatabaseComponent.class);
|
DatabaseComponent db = alice.getInstance(DatabaseComponent.class);
|
||||||
db.open(false);
|
db.open(false);
|
||||||
// Add Bob as a contact and send him a message
|
// Add Bob as a contact and send him a message
|
||||||
ContactId contactId = db.addContact(aliceSecret);
|
ContactId contactId = db.addContact(bobToAliceSecret, aliceToBobSecret);
|
||||||
String subject = "Hello";
|
String subject = "Hello";
|
||||||
byte[] messageBody = "Hi Bob!".getBytes("UTF-8");
|
byte[] messageBody = "Hi Bob!".getBytes("UTF-8");
|
||||||
MessageEncoder encoder = alice.getInstance(MessageEncoder.class);
|
MessageEncoder encoder = alice.getInstance(MessageEncoder.class);
|
||||||
@@ -134,7 +137,7 @@ public class BatchConnectionReadWriteTest extends TestCase {
|
|||||||
MessageListener listener = new MessageListener();
|
MessageListener listener = new MessageListener();
|
||||||
db.addListener(listener);
|
db.addListener(listener);
|
||||||
// Add Alice as a contact
|
// Add Alice as a contact
|
||||||
ContactId contactId = db.addContact(bobSecret);
|
ContactId contactId = db.addContact(aliceToBobSecret, bobToAliceSecret);
|
||||||
// Add the transport
|
// Add the transport
|
||||||
assertEquals(transportIndex, db.addTransport(transportId));
|
assertEquals(transportIndex, db.addTransport(transportId));
|
||||||
// Fake a transport update from Alice
|
// Fake a transport update from Alice
|
||||||
|
|||||||
Reference in New Issue
Block a user