mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-23 16:19:54 +01:00
Address second round of review comments
This commit is contained in:
@@ -16,8 +16,6 @@ import org.briarproject.bramble.api.sync.ValidationManager.IncomingMessageHook;
|
|||||||
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
|
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public abstract class BdfIncomingMessageHook implements IncomingMessageHook {
|
public abstract class BdfIncomingMessageHook implements IncomingMessageHook {
|
||||||
@@ -57,9 +55,7 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook {
|
|||||||
public boolean incomingMessage(Transaction txn, Message m, Metadata meta)
|
public boolean incomingMessage(Transaction txn, Message m, Metadata meta)
|
||||||
throws DbException, InvalidMessageException {
|
throws DbException, InvalidMessageException {
|
||||||
try {
|
try {
|
||||||
byte[] raw = m.getRaw();
|
BdfList body = clientHelper.toList(m);
|
||||||
BdfList body = clientHelper.toList(raw, MESSAGE_HEADER_LENGTH,
|
|
||||||
raw.length - MESSAGE_HEADER_LENGTH);
|
|
||||||
BdfDictionary metaDictionary = metadataParser.parse(meta);
|
BdfDictionary metaDictionary = metadataParser.parse(meta);
|
||||||
return incomingMessage(txn, m, body, metaDictionary);
|
return incomingMessage(txn, m, body, metaDictionary);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
|
|||||||
@@ -33,11 +33,13 @@ import org.briarproject.briar.api.introduction.event.IntroductionSucceededEvent;
|
|||||||
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.briar.api.introduction.Role.INTRODUCEE;
|
import static org.briarproject.briar.api.introduction.Role.INTRODUCEE;
|
||||||
import static org.briarproject.briar.introduction.IntroduceeState.AWAIT_AUTH;
|
import static org.briarproject.briar.introduction.IntroduceeState.AWAIT_AUTH;
|
||||||
import static org.briarproject.briar.introduction.IntroduceeState.AWAIT_RESPONSES;
|
import static org.briarproject.briar.introduction.IntroduceeState.AWAIT_RESPONSES;
|
||||||
@@ -51,6 +53,9 @@ import static org.briarproject.briar.introduction.IntroduceeState.START;
|
|||||||
class IntroduceeProtocolEngine
|
class IntroduceeProtocolEngine
|
||||||
extends AbstractProtocolEngine<IntroduceeSession> {
|
extends AbstractProtocolEngine<IntroduceeSession> {
|
||||||
|
|
||||||
|
private final static Logger LOG =
|
||||||
|
Logger.getLogger(IntroduceeProtocolEngine.class.getSimpleName());
|
||||||
|
|
||||||
private final IntroductionCrypto crypto;
|
private final IntroductionCrypto crypto;
|
||||||
private final KeyManager keyManager;
|
private final KeyManager keyManager;
|
||||||
private final TransportPropertyManager transportPropertyManager;
|
private final TransportPropertyManager transportPropertyManager;
|
||||||
@@ -383,11 +388,12 @@ class IntroduceeProtocolEngine
|
|||||||
bobMacKey = crypto.deriveMacKey(masterKey, false);
|
bobMacKey = crypto.deriveMacKey(masterKey, false);
|
||||||
SecretKey ourMacKey = s.getLocal().alice ? aliceMacKey : bobMacKey;
|
SecretKey ourMacKey = s.getLocal().alice ? aliceMacKey : bobMacKey;
|
||||||
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
||||||
mac = crypto.authMac(ourMacKey, s, localAuthor.getId(),
|
mac = crypto.authMac(ourMacKey, s, localAuthor.getId());
|
||||||
s.getLocal().alice);
|
|
||||||
signature = crypto.sign(ourMacKey, localAuthor.getPrivateKey());
|
signature = crypto.sign(ourMacKey, localAuthor.getPrivateKey());
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
// TODO
|
// TODO
|
||||||
|
if (LOG.isLoggable(WARNING))
|
||||||
|
LOG.log(WARNING, e.toString(), e);
|
||||||
return abort(txn, s);
|
return abort(txn, s);
|
||||||
}
|
}
|
||||||
if (s.getState() != AWAIT_AUTH) throw new AssertionError();
|
if (s.getState() != AWAIT_AUTH) throw new AssertionError();
|
||||||
@@ -406,7 +412,7 @@ class IntroduceeProtocolEngine
|
|||||||
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
||||||
try {
|
try {
|
||||||
crypto.verifyAuthMac(m.getMac(), s, localAuthor.getId());
|
crypto.verifyAuthMac(m.getMac(), s, localAuthor.getId());
|
||||||
crypto.verifySignature(m.getSignature(), s, localAuthor.getId());
|
crypto.verifySignature(m.getSignature(), s);
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
return abort(txn, s);
|
return abort(txn, s);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,8 +207,10 @@ class IntroducerProtocolEngine
|
|||||||
IntroducerSession s,
|
IntroducerSession s,
|
||||||
@Nullable String message, long timestamp) throws DbException {
|
@Nullable String message, long timestamp) throws DbException {
|
||||||
// Send REQUEST messages
|
// Send REQUEST messages
|
||||||
long localTimestamp =
|
long maxIntroduceeTimestamp =
|
||||||
Math.max(timestamp, getLocalTimestamp(s, s.getIntroduceeA()));
|
Math.max(getLocalTimestamp(s, s.getIntroduceeA()),
|
||||||
|
getLocalTimestamp(s, s.getIntroduceeB()));
|
||||||
|
long localTimestamp = Math.max(timestamp, maxIntroduceeTimestamp);
|
||||||
Message sentA = sendRequestMessage(txn, s.getIntroduceeA(),
|
Message sentA = sendRequestMessage(txn, s.getIntroduceeA(),
|
||||||
localTimestamp, s.getIntroduceeB().author, message
|
localTimestamp, s.getIntroduceeB().author, message
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ interface IntroductionCrypto {
|
|||||||
* transport properties, Author IDs and timestamps of the accept message.
|
* transport properties, Author IDs and timestamps of the accept message.
|
||||||
*/
|
*/
|
||||||
byte[] authMac(SecretKey macKey, IntroduceeSession s,
|
byte[] authMac(SecretKey macKey, IntroduceeSession s,
|
||||||
AuthorId localAuthorId, boolean alice);
|
AuthorId localAuthorId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies a received MAC
|
* Verifies a received MAC
|
||||||
@@ -74,12 +74,12 @@ interface IntroductionCrypto {
|
|||||||
throws GeneralSecurityException;
|
throws GeneralSecurityException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies the signature on a corresponding MAC key.
|
* Verifies the signature on a nonce derived from the MAC key.
|
||||||
*
|
*
|
||||||
* @throws GeneralSecurityException if the signature is invalid
|
* @throws GeneralSecurityException if the signature is invalid
|
||||||
*/
|
*/
|
||||||
void verifySignature(byte[] signature, IntroduceeSession s,
|
void verifySignature(byte[] signature, IntroduceeSession s)
|
||||||
AuthorId localAuthorId) throws GeneralSecurityException;
|
throws GeneralSecurityException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a MAC using the local MAC key.
|
* Generates a MAC using the local MAC key.
|
||||||
|
|||||||
@@ -13,12 +13,11 @@ import org.briarproject.bramble.api.data.BdfList;
|
|||||||
import org.briarproject.bramble.api.identity.Author;
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
import org.briarproject.bramble.api.identity.AuthorId;
|
import org.briarproject.bramble.api.identity.AuthorId;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.plugin.TransportId;
|
|
||||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
|
||||||
import org.briarproject.briar.api.client.SessionId;
|
import org.briarproject.briar.api.client.SessionId;
|
||||||
|
import org.briarproject.briar.introduction.IntroduceeSession.Common;
|
||||||
|
import org.briarproject.briar.introduction.IntroduceeSession.Remote;
|
||||||
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -32,6 +31,7 @@ import static org.briarproject.briar.api.introduction.IntroductionConstants.LABE
|
|||||||
import static org.briarproject.briar.api.introduction.IntroductionConstants.LABEL_MASTER_KEY;
|
import static org.briarproject.briar.api.introduction.IntroductionConstants.LABEL_MASTER_KEY;
|
||||||
import static org.briarproject.briar.api.introduction.IntroductionConstants.LABEL_SESSION_ID;
|
import static org.briarproject.briar.api.introduction.IntroductionConstants.LABEL_SESSION_ID;
|
||||||
import static org.briarproject.briar.api.introduction.IntroductionManager.CLIENT_VERSION;
|
import static org.briarproject.briar.api.introduction.IntroductionManager.CLIENT_VERSION;
|
||||||
|
import static org.briarproject.briar.introduction.IntroduceeSession.Local;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -114,27 +114,16 @@ class IntroductionCryptoImpl implements IntroductionCrypto {
|
|||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
public byte[] authMac(SecretKey macKey, IntroduceeSession s,
|
public byte[] authMac(SecretKey macKey, IntroduceeSession s,
|
||||||
AuthorId localAuthorId, boolean alice) {
|
AuthorId localAuthorId) {
|
||||||
|
// the macKey is not yet available in the session at this point
|
||||||
return authMac(macKey, s.getIntroducer().getId(), localAuthorId,
|
return authMac(macKey, s.getIntroducer().getId(), localAuthorId,
|
||||||
s.getRemote().author.getId(), s.getLocal().acceptTimestamp,
|
s.getLocal(), s.getRemote());
|
||||||
s.getRemote().acceptTimestamp, s.getLocal().ephemeralPublicKey,
|
|
||||||
s.getRemote().ephemeralPublicKey,
|
|
||||||
s.getLocal().transportProperties,
|
|
||||||
s.getRemote().transportProperties, alice);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] authMac(SecretKey macKey, AuthorId introducerId,
|
byte[] authMac(SecretKey macKey, AuthorId introducerId,
|
||||||
AuthorId localAuthorId, AuthorId remoteAuthorId,
|
AuthorId localAuthorId, Local local, Remote remote) {
|
||||||
long acceptTimestamp, long remoteAcceptTimestamp,
|
byte[] inputs = getAuthMacInputs(introducerId, localAuthorId, local,
|
||||||
byte[] ephemeralPublicKey, byte[] remoteEphemeralPublicKey,
|
remote.author.getId(), remote);
|
||||||
Map<TransportId, TransportProperties> transportProperties,
|
|
||||||
Map<TransportId, TransportProperties> remoteTransportProperties,
|
|
||||||
boolean alice) {
|
|
||||||
byte[] inputs =
|
|
||||||
getAuthMacInputs(introducerId, localAuthorId, remoteAuthorId,
|
|
||||||
acceptTimestamp, remoteAcceptTimestamp,
|
|
||||||
ephemeralPublicKey, remoteEphemeralPublicKey,
|
|
||||||
transportProperties, remoteTransportProperties, alice);
|
|
||||||
return crypto.mac(
|
return crypto.mac(
|
||||||
LABEL_AUTH_MAC,
|
LABEL_AUTH_MAC,
|
||||||
macKey,
|
macKey,
|
||||||
@@ -145,59 +134,43 @@ class IntroductionCryptoImpl implements IntroductionCrypto {
|
|||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
public void verifyAuthMac(byte[] mac, IntroduceeSession s,
|
public void verifyAuthMac(byte[] mac, IntroduceeSession s,
|
||||||
AuthorId localAuthorId)
|
AuthorId localAuthorId) throws GeneralSecurityException {
|
||||||
throws GeneralSecurityException {
|
|
||||||
boolean alice = isAlice(localAuthorId, s.getRemote().author.getId());
|
|
||||||
verifyAuthMac(mac, new SecretKey(s.getRemote().macKey),
|
verifyAuthMac(mac, new SecretKey(s.getRemote().macKey),
|
||||||
s.getIntroducer().getId(), localAuthorId,
|
s.getIntroducer().getId(), localAuthorId, s.getLocal(),
|
||||||
s.getRemote().author.getId(), s.getLocal().acceptTimestamp,
|
s.getRemote().author.getId(), s.getRemote());
|
||||||
s.getRemote().acceptTimestamp, s.getLocal().ephemeralPublicKey,
|
|
||||||
s.getRemote().ephemeralPublicKey,
|
|
||||||
s.getLocal().transportProperties,
|
|
||||||
s.getRemote().transportProperties, !alice);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void verifyAuthMac(byte[] mac, SecretKey macKey,
|
void verifyAuthMac(byte[] mac, SecretKey macKey, AuthorId introducerId,
|
||||||
AuthorId introducerId, AuthorId localAuthorId,
|
AuthorId localAuthorId, Common local, AuthorId remoteAuthorId,
|
||||||
AuthorId remoteAuthorId, long acceptTimestamp,
|
Common remote) throws GeneralSecurityException {
|
||||||
long remoteAcceptTimestamp, byte[] ephemeralPublicKey,
|
// switch input for verification
|
||||||
byte[] remoteEphemeralPublicKey,
|
byte[] inputs = getAuthMacInputs(introducerId, remoteAuthorId, remote,
|
||||||
Map<TransportId, TransportProperties> transportProperties,
|
localAuthorId, local);
|
||||||
Map<TransportId, TransportProperties> remoteTransportProperties,
|
|
||||||
boolean alice) throws GeneralSecurityException {
|
|
||||||
byte[] inputs =
|
|
||||||
getAuthMacInputs(introducerId, localAuthorId, remoteAuthorId,
|
|
||||||
acceptTimestamp, remoteAcceptTimestamp,
|
|
||||||
ephemeralPublicKey, remoteEphemeralPublicKey,
|
|
||||||
transportProperties, remoteTransportProperties, !alice);
|
|
||||||
if (!crypto.verifyMac(mac, LABEL_AUTH_MAC, macKey, inputs)) {
|
if (!crypto.verifyMac(mac, LABEL_AUTH_MAC, macKey, inputs)) {
|
||||||
throw new GeneralSecurityException();
|
throw new GeneralSecurityException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
private byte[] getAuthMacInputs(AuthorId introducerId,
|
private byte[] getAuthMacInputs(AuthorId introducerId,
|
||||||
AuthorId localAuthorId, AuthorId remoteAuthorId,
|
AuthorId localAuthorId, Common local, AuthorId remoteAuthorId,
|
||||||
long acceptTimestamp, long remoteAcceptTimestamp,
|
Common remote) {
|
||||||
byte[] ephemeralPublicKey, byte[] remoteEphemeralPublicKey,
|
|
||||||
Map<TransportId, TransportProperties> transportProperties,
|
|
||||||
Map<TransportId, TransportProperties> remoteTransportProperties,
|
|
||||||
boolean alice) {
|
|
||||||
BdfList localInfo = BdfList.of(
|
BdfList localInfo = BdfList.of(
|
||||||
localAuthorId,
|
localAuthorId,
|
||||||
acceptTimestamp,
|
local.acceptTimestamp,
|
||||||
ephemeralPublicKey,
|
local.ephemeralPublicKey,
|
||||||
clientHelper.toDictionary(transportProperties)
|
clientHelper.toDictionary(local.transportProperties)
|
||||||
);
|
);
|
||||||
BdfList remoteInfo = BdfList.of(
|
BdfList remoteInfo = BdfList.of(
|
||||||
remoteAuthorId,
|
remoteAuthorId,
|
||||||
remoteAcceptTimestamp,
|
remote.acceptTimestamp,
|
||||||
remoteEphemeralPublicKey,
|
remote.ephemeralPublicKey,
|
||||||
clientHelper.toDictionary(remoteTransportProperties)
|
clientHelper.toDictionary(remote.transportProperties)
|
||||||
);
|
);
|
||||||
BdfList macList = BdfList.of(
|
BdfList macList = BdfList.of(
|
||||||
introducerId,
|
introducerId,
|
||||||
alice ? localInfo : remoteInfo,
|
localInfo,
|
||||||
alice ? remoteInfo : localInfo
|
remoteInfo
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
return clientHelper.toByteArray(macList);
|
return clientHelper.toByteArray(macList);
|
||||||
@@ -218,8 +191,8 @@ class IntroductionCryptoImpl implements IntroductionCrypto {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
public void verifySignature(byte[] signature, IntroduceeSession s,
|
public void verifySignature(byte[] signature, IntroduceeSession s)
|
||||||
AuthorId localAuthorId) throws GeneralSecurityException {
|
throws GeneralSecurityException {
|
||||||
SecretKey macKey = new SecretKey(s.getRemote().macKey);
|
SecretKey macKey = new SecretKey(s.getRemote().macKey);
|
||||||
verifySignature(macKey, s.getRemote().author.getPublicKey(), signature);
|
verifySignature(macKey, s.getRemote().author.getPublicKey(), signature);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
private final IntroductionCrypto crypto;
|
private final IntroductionCrypto crypto;
|
||||||
private final IdentityManager identityManager;
|
private final IdentityManager identityManager;
|
||||||
|
|
||||||
|
private final Group localGroup;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
IntroductionManagerImpl(
|
IntroductionManagerImpl(
|
||||||
DatabaseComponent db,
|
DatabaseComponent db,
|
||||||
@@ -96,12 +98,13 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
this.introduceeEngine = introduceeEngine;
|
this.introduceeEngine = introduceeEngine;
|
||||||
this.crypto = crypto;
|
this.crypto = crypto;
|
||||||
this.identityManager = identityManager;
|
this.identityManager = identityManager;
|
||||||
|
this.localGroup =
|
||||||
|
contactGroupFactory.createLocalGroup(CLIENT_ID, CLIENT_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createLocalState(Transaction txn) throws DbException {
|
public void createLocalState(Transaction txn) throws DbException {
|
||||||
// Create a local group to store protocol sessions
|
// Create a local group to store protocol sessions
|
||||||
Group localGroup = getLocalGroup();
|
|
||||||
if (db.containsGroup(txn, localGroup.getId())) return;
|
if (db.containsGroup(txn, localGroup.getId())) return;
|
||||||
db.addGroup(txn, localGroup);
|
db.addGroup(txn, localGroup);
|
||||||
// Set up groups for communication with any pre-existing contacts
|
// Set up groups for communication with any pre-existing contacts
|
||||||
@@ -229,8 +232,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
if (sessionId == null) return null;
|
if (sessionId == null) return null;
|
||||||
BdfDictionary query = sessionParser.getSessionQuery(sessionId);
|
BdfDictionary query = sessionParser.getSessionQuery(sessionId);
|
||||||
Map<MessageId, BdfDictionary> results = clientHelper
|
Map<MessageId, BdfDictionary> results = clientHelper
|
||||||
.getMessageMetadataAsDictionary(txn, getLocalGroup().getId(),
|
.getMessageMetadataAsDictionary(txn, localGroup.getId(), query);
|
||||||
query);
|
|
||||||
if (results.size() > 1) throw new DbException();
|
if (results.size() > 1) throw new DbException();
|
||||||
if (results.isEmpty()) return null;
|
if (results.isEmpty()) return null;
|
||||||
return new StoredSession(results.keySet().iterator().next(),
|
return new StoredSession(results.keySet().iterator().next(),
|
||||||
@@ -246,7 +248,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
|
|
||||||
private MessageId createStorageId(Transaction txn) throws DbException {
|
private MessageId createStorageId(Transaction txn) throws DbException {
|
||||||
Message m = clientHelper
|
Message m = clientHelper
|
||||||
.createMessageForStoringMetadata(getLocalGroup().getId());
|
.createMessageForStoringMetadata(localGroup.getId());
|
||||||
db.addLocalMessage(txn, m, new Metadata(), false);
|
db.addLocalMessage(txn, m, new Metadata(), false);
|
||||||
return m.getId();
|
return m.getId();
|
||||||
}
|
}
|
||||||
@@ -274,22 +276,28 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
public boolean canIntroduce(Contact c1, Contact c2) throws DbException {
|
public boolean canIntroduce(Contact c1, Contact c2) throws DbException {
|
||||||
Transaction txn = db.startTransaction(true);
|
Transaction txn = db.startTransaction(true);
|
||||||
try {
|
try {
|
||||||
// Look up the session, if there is one
|
boolean can = canIntroduce(txn, c1, c2);
|
||||||
Author introducer = identityManager.getLocalAuthor(txn);
|
db.commitTransaction(txn);
|
||||||
SessionId sessionId =
|
return can;
|
||||||
crypto.getSessionId(introducer, c1.getAuthor(),
|
|
||||||
c2.getAuthor());
|
|
||||||
StoredSession ss = getSession(txn, sessionId);
|
|
||||||
if (ss == null) return true;
|
|
||||||
IntroducerSession session =
|
|
||||||
sessionParser.parseIntroducerSession(ss.bdfSession);
|
|
||||||
if (session.getState() == START) return true;
|
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(txn);
|
db.endTransaction(txn);
|
||||||
}
|
}
|
||||||
return false;
|
}
|
||||||
|
|
||||||
|
private boolean canIntroduce(Transaction txn, Contact c1, Contact c2)
|
||||||
|
throws DbException, FormatException {
|
||||||
|
// Look up the session, if there is one
|
||||||
|
Author introducer = identityManager.getLocalAuthor(txn);
|
||||||
|
SessionId sessionId =
|
||||||
|
crypto.getSessionId(introducer, c1.getAuthor(),
|
||||||
|
c2.getAuthor());
|
||||||
|
StoredSession ss = getSession(txn, sessionId);
|
||||||
|
if (ss == null) return true;
|
||||||
|
IntroducerSession session =
|
||||||
|
sessionParser.parseIntroducerSession(ss.bdfSession);
|
||||||
|
return session.getState() == START;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -395,12 +403,12 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
meta, status, ss.bdfSession));
|
meta, status, ss.bdfSession));
|
||||||
} else if (type == ACCEPT) {
|
} else if (type == ACCEPT) {
|
||||||
messages.add(
|
messages.add(
|
||||||
parseInvitationResponse(txn, contactGroupId, m,
|
parseInvitationResponse(contactGroupId, m, meta,
|
||||||
meta, status, ss.bdfSession, true));
|
status, ss.bdfSession, true));
|
||||||
} else if (type == DECLINE) {
|
} else if (type == DECLINE) {
|
||||||
messages.add(
|
messages.add(
|
||||||
parseInvitationResponse(txn, contactGroupId, m,
|
parseInvitationResponse(contactGroupId, m, meta,
|
||||||
meta, status, ss.bdfSession, false));
|
status, ss.bdfSession, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
@@ -435,8 +443,8 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
author = session.getRemote().author;
|
author = session.getRemote().author;
|
||||||
} else throw new AssertionError();
|
} else throw new AssertionError();
|
||||||
Message msg = clientHelper.getMessage(txn, m);
|
Message msg = clientHelper.getMessage(txn, m);
|
||||||
BdfList body = clientHelper.getMessageAsList(txn, m);
|
if (msg == null) throw new AssertionError();
|
||||||
if (msg == null || body == null) throw new AssertionError();
|
BdfList body = clientHelper.toList(msg);
|
||||||
RequestMessage rm = messageParser.parseRequestMessage(msg, body);
|
RequestMessage rm = messageParser.parseRequestMessage(msg, body);
|
||||||
String message = rm.getMessage();
|
String message = rm.getMessage();
|
||||||
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
||||||
@@ -451,10 +459,9 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
contactExists);
|
contactExists);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntroductionResponse parseInvitationResponse(Transaction txn,
|
private IntroductionResponse parseInvitationResponse(GroupId contactGroupId,
|
||||||
GroupId contactGroupId, MessageId m, MessageMetadata meta,
|
MessageId m, MessageMetadata meta, MessageStatus status,
|
||||||
MessageStatus status, BdfDictionary bdfSession, boolean accept)
|
BdfDictionary bdfSession, boolean accept) throws FormatException {
|
||||||
throws FormatException, DbException {
|
|
||||||
Role role = sessionParser.getRole(bdfSession);
|
Role role = sessionParser.getRole(bdfSession);
|
||||||
SessionId sessionId;
|
SessionId sessionId;
|
||||||
Author author;
|
Author author;
|
||||||
@@ -462,8 +469,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
IntroducerSession session =
|
IntroducerSession session =
|
||||||
sessionParser.parseIntroducerSession(bdfSession);
|
sessionParser.parseIntroducerSession(bdfSession);
|
||||||
sessionId = session.getSessionId();
|
sessionId = session.getSessionId();
|
||||||
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
if (contactGroupId.equals(session.getIntroduceeA().groupId)) {
|
||||||
if (localAuthor.equals(session.getIntroduceeA().author)) {
|
|
||||||
author = session.getIntroduceeB().author;
|
author = session.getIntroduceeB().author;
|
||||||
} else {
|
} else {
|
||||||
author = session.getIntroduceeA().author;
|
author = session.getIntroduceeA().author;
|
||||||
@@ -485,13 +491,13 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
.getIntroduceeSessionsByIntroducerQuery(introducer.getAuthor());
|
.getIntroduceeSessionsByIntroducerQuery(introducer.getAuthor());
|
||||||
Map<MessageId, BdfDictionary> sessions;
|
Map<MessageId, BdfDictionary> sessions;
|
||||||
try {
|
try {
|
||||||
sessions = clientHelper.getMessageMetadataAsDictionary(txn,
|
sessions = clientHelper
|
||||||
getLocalGroup().getId(), query);
|
.getMessageMetadataAsDictionary(txn, localGroup.getId(),
|
||||||
|
query);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new AssertionError(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
for (MessageId id : sessions.keySet()) {
|
for (MessageId id : sessions.keySet()) {
|
||||||
db.deleteMessageMetadata(txn, id); // TODO needed?
|
|
||||||
db.removeMessage(txn, id);
|
db.removeMessage(txn, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -501,10 +507,11 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
BdfDictionary query = sessionEncoder.getIntroducerSessionsQuery();
|
BdfDictionary query = sessionEncoder.getIntroducerSessionsQuery();
|
||||||
Map<MessageId, BdfDictionary> sessions;
|
Map<MessageId, BdfDictionary> sessions;
|
||||||
try {
|
try {
|
||||||
sessions = clientHelper.getMessageMetadataAsDictionary(txn,
|
sessions = clientHelper
|
||||||
getLocalGroup().getId(), query);
|
.getMessageMetadataAsDictionary(txn, localGroup.getId(),
|
||||||
|
query);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new AssertionError();
|
throw new DbException();
|
||||||
}
|
}
|
||||||
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
||||||
for (Entry<MessageId, BdfDictionary> session : sessions.entrySet()) {
|
for (Entry<MessageId, BdfDictionary> session : sessions.entrySet()) {
|
||||||
@@ -512,7 +519,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
try {
|
try {
|
||||||
s = sessionParser.parseIntroducerSession(session.getValue());
|
s = sessionParser.parseIntroducerSession(session.getValue());
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new AssertionError();
|
throw new DbException();
|
||||||
}
|
}
|
||||||
if (s.getIntroduceeA().author.equals(c.getAuthor())) {
|
if (s.getIntroduceeA().author.equals(c.getAuthor())) {
|
||||||
abortOrRemoveSessionWithIntroducee(txn, s, session.getKey(),
|
abortOrRemoveSessionWithIntroducee(txn, s, session.getKey(),
|
||||||
@@ -531,15 +538,10 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
IntroducerSession session = introducerEngine.onAbortAction(txn, s);
|
IntroducerSession session = introducerEngine.onAbortAction(txn, s);
|
||||||
storeSession(txn, storageId, session);
|
storeSession(txn, storageId, session);
|
||||||
} else {
|
} else {
|
||||||
db.deleteMessageMetadata(txn, storageId); // TODO needed?
|
|
||||||
db.removeMessage(txn, storageId);
|
db.removeMessage(txn, storageId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Group getLocalGroup() {
|
|
||||||
return contactGroupFactory.createLocalGroup(CLIENT_ID, CLIENT_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class StoredSession {
|
private static class StoredSession {
|
||||||
|
|
||||||
private final MessageId storageId;
|
private final MessageId storageId;
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import javax.annotation.concurrent.Immutable;
|
|||||||
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAC_BYTES;
|
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAC_BYTES;
|
||||||
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_SIGNATURE_BYTES;
|
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_SIGNATURE_BYTES;
|
||||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||||
import static org.briarproject.bramble.api.plugin.TransportId.MAX_TRANSPORT_ID_LENGTH;
|
|
||||||
import static org.briarproject.bramble.util.ValidationUtils.checkLength;
|
import static org.briarproject.bramble.util.ValidationUtils.checkLength;
|
||||||
import static org.briarproject.bramble.util.ValidationUtils.checkSize;
|
import static org.briarproject.bramble.util.ValidationUtils.checkSize;
|
||||||
import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_REQUEST_MESSAGE_LENGTH;
|
import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_REQUEST_MESSAGE_LENGTH;
|
||||||
@@ -79,8 +78,8 @@ class IntroductionValidator extends BdfMessageValidator {
|
|||||||
String msg = body.getOptionalString(3);
|
String msg = body.getOptionalString(3);
|
||||||
checkLength(msg, 1, MAX_REQUEST_MESSAGE_LENGTH);
|
checkLength(msg, 1, MAX_REQUEST_MESSAGE_LENGTH);
|
||||||
|
|
||||||
BdfDictionary meta = messageEncoder
|
BdfDictionary meta =
|
||||||
.encodeRequestMetadata(m.getTimestamp(), false, false, false);
|
messageEncoder.encodeRequestMetadata(m.getTimestamp());
|
||||||
if (previousMessageId == null) {
|
if (previousMessageId == null) {
|
||||||
return new BdfMessageContext(meta);
|
return new BdfMessageContext(meta);
|
||||||
} else {
|
} else {
|
||||||
@@ -103,15 +102,13 @@ class IntroductionValidator extends BdfMessageValidator {
|
|||||||
byte[] ephemeralPublicKey = body.getRaw(3);
|
byte[] ephemeralPublicKey = body.getRaw(3);
|
||||||
checkLength(ephemeralPublicKey, 0, MAX_PUBLIC_KEY_LENGTH);
|
checkLength(ephemeralPublicKey, 0, MAX_PUBLIC_KEY_LENGTH);
|
||||||
|
|
||||||
body.getLong(4);
|
long timestamp = body.getLong(4);
|
||||||
|
if (timestamp < 0) throw new FormatException();
|
||||||
|
|
||||||
BdfDictionary transportProperties = body.getDictionary(5);
|
BdfDictionary transportProperties = body.getDictionary(5);
|
||||||
if (transportProperties.size() < 1) throw new FormatException();
|
if (transportProperties.size() < 1) throw new FormatException();
|
||||||
for (String tId : transportProperties.keySet()) {
|
clientHelper
|
||||||
checkLength(tId, 1, MAX_TRANSPORT_ID_LENGTH);
|
.parseAndValidateTransportPropertiesMap(transportProperties);
|
||||||
BdfDictionary tProps = transportProperties.getDictionary(tId);
|
|
||||||
clientHelper.parseAndValidateTransportProperties(tProps);
|
|
||||||
}
|
|
||||||
|
|
||||||
SessionId sessionId = new SessionId(sessionIdBytes);
|
SessionId sessionId = new SessionId(sessionIdBytes);
|
||||||
BdfDictionary meta = messageEncoder
|
BdfDictionary meta = messageEncoder
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ import javax.annotation.Nullable;
|
|||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
interface MessageEncoder {
|
interface MessageEncoder {
|
||||||
|
|
||||||
BdfDictionary encodeRequestMetadata(long timestamp, boolean local,
|
BdfDictionary encodeRequestMetadata(long timestamp);
|
||||||
boolean read, boolean available);
|
|
||||||
|
|
||||||
BdfDictionary encodeMetadata(MessageType type,
|
BdfDictionary encodeMetadata(MessageType type,
|
||||||
@Nullable SessionId sessionId, long timestamp, boolean local,
|
@Nullable SessionId sessionId, long timestamp, boolean local,
|
||||||
|
|||||||
@@ -47,11 +47,10 @@ class MessageEncoderImpl implements MessageEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BdfDictionary encodeRequestMetadata(long timestamp,
|
public BdfDictionary encodeRequestMetadata(long timestamp) {
|
||||||
boolean local, boolean read, boolean available) {
|
|
||||||
BdfDictionary meta =
|
BdfDictionary meta =
|
||||||
encodeMetadata(REQUEST, null, timestamp, local, read, false);
|
encodeMetadata(REQUEST, null, timestamp, false, false, false);
|
||||||
meta.put(MSG_KEY_AVAILABLE_TO_ANSWER, available);
|
meta.put(MSG_KEY_AVAILABLE_TO_ANSWER, false);
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,23 +11,25 @@ import org.briarproject.bramble.api.plugin.TransportId;
|
|||||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.briar.api.client.SessionId;
|
import org.briarproject.briar.api.client.SessionId;
|
||||||
import org.briarproject.briar.test.BriarIntegrationTestComponent;
|
|
||||||
import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getTransportPropertiesMap;
|
import static org.briarproject.bramble.test.TestUtils.getTransportPropertiesMap;
|
||||||
import static org.briarproject.bramble.util.StringUtils.fromHexString;
|
import static org.briarproject.briar.introduction.IntroduceeSession.Local;
|
||||||
|
import static org.briarproject.briar.introduction.IntroduceeSession.Remote;
|
||||||
|
import static org.briarproject.briar.test.BriarTestUtils.getRealAuthor;
|
||||||
|
import static org.briarproject.briar.test.BriarTestUtils.getRealLocalAuthor;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class IntroductionCryptoImplTest extends BrambleTestCase {
|
public class IntroductionCryptoIntegrationTest extends BrambleTestCase {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ClientHelper clientHelper;
|
ClientHelper clientHelper;
|
||||||
@@ -42,33 +44,28 @@ public class IntroductionCryptoImplTest extends BrambleTestCase {
|
|||||||
private final LocalAuthor alice, bob;
|
private final LocalAuthor alice, bob;
|
||||||
private final long aliceAcceptTimestamp = 42L;
|
private final long aliceAcceptTimestamp = 42L;
|
||||||
private final long bobAcceptTimestamp = 1337L;
|
private final long bobAcceptTimestamp = 1337L;
|
||||||
private final SecretKey masterKey =
|
private final SecretKey masterKey = getSecretKey();
|
||||||
new SecretKey(getRandomBytes(SecretKey.LENGTH));
|
|
||||||
private final KeyPair aliceEphemeral, bobEphemeral;
|
private final KeyPair aliceEphemeral, bobEphemeral;
|
||||||
private final Map<TransportId, TransportProperties> aliceTransport =
|
private final Map<TransportId, TransportProperties> aliceTransport =
|
||||||
getTransportPropertiesMap(3);
|
getTransportPropertiesMap(3);
|
||||||
private final Map<TransportId, TransportProperties> bobTransport =
|
private final Map<TransportId, TransportProperties> bobTransport =
|
||||||
getTransportPropertiesMap(3);
|
getTransportPropertiesMap(3);
|
||||||
|
|
||||||
public IntroductionCryptoImplTest() {
|
public IntroductionCryptoIntegrationTest() {
|
||||||
BriarIntegrationTestComponent component =
|
IntroductionIntegrationTestComponent component =
|
||||||
DaggerBriarIntegrationTestComponent.builder().build();
|
DaggerIntroductionIntegrationTestComponent.builder().build();
|
||||||
component.inject(this);
|
component.inject(this);
|
||||||
crypto = new IntroductionCryptoImpl(cryptoComponent, clientHelper);
|
crypto = new IntroductionCryptoImpl(cryptoComponent, clientHelper);
|
||||||
|
|
||||||
// create actual deterministic authors for testing
|
introducer = getRealAuthor(authorFactory);
|
||||||
introducer = authorFactory
|
LocalAuthor introducee1 =
|
||||||
.createAuthor("Introducer", new byte[] {0x1, 0x2, 0x3});
|
getRealLocalAuthor(cryptoComponent, authorFactory);
|
||||||
alice = authorFactory.createLocalAuthor("Alice",
|
LocalAuthor introducee2 =
|
||||||
fromHexString(
|
getRealLocalAuthor(cryptoComponent, authorFactory);
|
||||||
"A626F080C94771698F86B4B4094C4F560904B53398805AE02BA2343F1829187A"),
|
boolean isAlice =
|
||||||
fromHexString(
|
crypto.isAlice(introducee1.getId(), introducee2.getId());
|
||||||
"60F010187AF91ACA15141E8C811EC8E79C7CAA6461C21A852BB03066C89B0A70"));
|
alice = isAlice ? introducee1 : introducee2;
|
||||||
bob = authorFactory.createLocalAuthor("Bob",
|
bob = isAlice ? introducee2 : introducee1;
|
||||||
fromHexString(
|
|
||||||
"A0D0FED1CE4674D8B6441AD0A664E41BF60D489F35DA11F52AF923540848546F"),
|
|
||||||
fromHexString(
|
|
||||||
"20B25BE7E999F68FE07189449E91984FA79121DBFF28A651669A3CF512D6A758"));
|
|
||||||
aliceEphemeral = crypto.generateKeyPair();
|
aliceEphemeral = crypto.generateKeyPair();
|
||||||
bobEphemeral = crypto.generateKeyPair();
|
bobEphemeral = crypto.generateKeyPair();
|
||||||
}
|
}
|
||||||
@@ -78,6 +75,9 @@ public class IntroductionCryptoImplTest extends BrambleTestCase {
|
|||||||
SessionId s1 = crypto.getSessionId(introducer, alice, bob);
|
SessionId s1 = crypto.getSessionId(introducer, alice, bob);
|
||||||
SessionId s2 = crypto.getSessionId(introducer, bob, alice);
|
SessionId s2 = crypto.getSessionId(introducer, bob, alice);
|
||||||
assertEquals(s1, s2);
|
assertEquals(s1, s2);
|
||||||
|
|
||||||
|
SessionId s3 = crypto.getSessionId(alice, bob, introducer);
|
||||||
|
assertNotEquals(s1, s3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -88,62 +88,66 @@ public class IntroductionCryptoImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeriveMasterKey() throws Exception {
|
public void testDeriveMasterKey() throws Exception {
|
||||||
SecretKey aliceMasterKey = crypto.deriveMasterKey(alice.getPublicKey(),
|
SecretKey aliceMasterKey =
|
||||||
alice.getPrivateKey(), bob.getPublicKey(), true);
|
crypto.deriveMasterKey(aliceEphemeral.getPublic().getEncoded(),
|
||||||
SecretKey bobMasterKey = crypto.deriveMasterKey(bob.getPublicKey(),
|
aliceEphemeral.getPrivate().getEncoded(),
|
||||||
bob.getPrivateKey(), alice.getPublicKey(), false);
|
bobEphemeral.getPublic().getEncoded(), true);
|
||||||
|
SecretKey bobMasterKey =
|
||||||
|
crypto.deriveMasterKey(bobEphemeral.getPublic().getEncoded(),
|
||||||
|
bobEphemeral.getPrivate().getEncoded(),
|
||||||
|
aliceEphemeral.getPublic().getEncoded(), false);
|
||||||
assertArrayEquals(aliceMasterKey.getBytes(), bobMasterKey.getBytes());
|
assertArrayEquals(aliceMasterKey.getBytes(), bobMasterKey.getBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAliceAuthMac() throws Exception {
|
public void testAliceAuthMac() throws Exception {
|
||||||
SecretKey aliceMacKey = crypto.deriveMacKey(masterKey, true);
|
SecretKey aliceMacKey = crypto.deriveMacKey(masterKey, true);
|
||||||
|
Local local = new Local(true, null, -1,
|
||||||
|
aliceEphemeral.getPublic().getEncoded(),
|
||||||
|
aliceEphemeral.getPrivate().getEncoded(), aliceTransport,
|
||||||
|
aliceAcceptTimestamp, aliceMacKey.getBytes());
|
||||||
|
Remote remote = new Remote(false, bob, null,
|
||||||
|
bobEphemeral.getPublic().getEncoded(), bobTransport,
|
||||||
|
bobAcceptTimestamp, null);
|
||||||
byte[] aliceMac =
|
byte[] aliceMac =
|
||||||
crypto.authMac(aliceMacKey, introducer.getId(), alice.getId(),
|
crypto.authMac(aliceMacKey, introducer.getId(), alice.getId(),
|
||||||
bob.getId(), aliceAcceptTimestamp, bobAcceptTimestamp,
|
local, remote);
|
||||||
aliceEphemeral.getPublic().getEncoded(),
|
|
||||||
bobEphemeral.getPublic().getEncoded(), aliceTransport,
|
|
||||||
bobTransport, true);
|
|
||||||
|
|
||||||
|
// verify from Bob's perspective
|
||||||
crypto.verifyAuthMac(aliceMac, aliceMacKey, introducer.getId(),
|
crypto.verifyAuthMac(aliceMac, aliceMacKey, introducer.getId(),
|
||||||
bob.getId(), alice.getId(), bobAcceptTimestamp,
|
bob.getId(), remote, alice.getId(), local);
|
||||||
aliceAcceptTimestamp, bobEphemeral.getPublic().getEncoded(),
|
|
||||||
aliceEphemeral.getPublic().getEncoded(), bobTransport,
|
|
||||||
aliceTransport, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBobAuthMac() throws Exception {
|
public void testBobAuthMac() throws Exception {
|
||||||
SecretKey bobMacKey = crypto.deriveMacKey(masterKey, false);
|
SecretKey bobMacKey = crypto.deriveMacKey(masterKey, false);
|
||||||
|
Local local = new Local(false, null, -1,
|
||||||
|
bobEphemeral.getPublic().getEncoded(),
|
||||||
|
bobEphemeral.getPrivate().getEncoded(), bobTransport,
|
||||||
|
bobAcceptTimestamp, bobMacKey.getBytes());
|
||||||
|
Remote remote = new Remote(true, alice, null,
|
||||||
|
aliceEphemeral.getPublic().getEncoded(), aliceTransport,
|
||||||
|
aliceAcceptTimestamp, null);
|
||||||
byte[] bobMac =
|
byte[] bobMac =
|
||||||
crypto.authMac(bobMacKey, introducer.getId(), bob.getId(),
|
crypto.authMac(bobMacKey, introducer.getId(), bob.getId(),
|
||||||
alice.getId(), bobAcceptTimestamp, aliceAcceptTimestamp,
|
local, remote);
|
||||||
bobEphemeral.getPublic().getEncoded(),
|
|
||||||
aliceEphemeral.getPublic().getEncoded(), bobTransport,
|
|
||||||
aliceTransport, false);
|
|
||||||
|
|
||||||
|
// verify from Alice's perspective
|
||||||
crypto.verifyAuthMac(bobMac, bobMacKey, introducer.getId(),
|
crypto.verifyAuthMac(bobMac, bobMacKey, introducer.getId(),
|
||||||
alice.getId(), bob.getId(), aliceAcceptTimestamp,
|
alice.getId(), remote, bob.getId(), local);
|
||||||
bobAcceptTimestamp, aliceEphemeral.getPublic().getEncoded(),
|
|
||||||
bobEphemeral.getPublic().getEncoded(), aliceTransport,
|
|
||||||
bobTransport, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSign() throws Exception {
|
public void testSign() throws Exception {
|
||||||
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair();
|
|
||||||
SecretKey macKey = crypto.deriveMacKey(masterKey, true);
|
SecretKey macKey = crypto.deriveMacKey(masterKey, true);
|
||||||
byte[] signature =
|
byte[] signature = crypto.sign(macKey, alice.getPrivateKey());
|
||||||
crypto.sign(macKey, keyPair.getPrivate().getEncoded());
|
crypto.verifySignature(macKey, alice.getPublicKey(), signature);
|
||||||
crypto.verifySignature(macKey, keyPair.getPublic().getEncoded(),
|
|
||||||
signature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAliceActivateMac() throws Exception {
|
public void testAliceActivateMac() throws Exception {
|
||||||
SecretKey aliceMacKey = crypto.deriveMacKey(masterKey, true);
|
SecretKey aliceMacKey = crypto.deriveMacKey(masterKey, true);
|
||||||
byte[] aliceMac = crypto.activateMac(aliceMacKey);
|
byte[] aliceMac = crypto.activateMac(aliceMacKey);
|
||||||
|
|
||||||
crypto.verifyActivateMac(aliceMac, aliceMacKey);
|
crypto.verifyActivateMac(aliceMac, aliceMacKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +155,6 @@ public class IntroductionCryptoImplTest extends BrambleTestCase {
|
|||||||
public void testBobActivateMac() throws Exception {
|
public void testBobActivateMac() throws Exception {
|
||||||
SecretKey bobMacKey = crypto.deriveMacKey(masterKey, false);
|
SecretKey bobMacKey = crypto.deriveMacKey(masterKey, false);
|
||||||
byte[] bobMac = crypto.activateMac(bobMacKey);
|
byte[] bobMac = crypto.activateMac(bobMacKey);
|
||||||
|
|
||||||
crypto.verifyActivateMac(bobMac, bobMacKey);
|
crypto.verifyActivateMac(bobMac, bobMacKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.briarproject.briar.introduction;
|
package org.briarproject.briar.introduction;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.UniqueId;
|
|
||||||
import org.briarproject.bramble.api.client.ClientHelper;
|
import org.briarproject.bramble.api.client.ClientHelper;
|
||||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
import org.briarproject.bramble.api.identity.Author;
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
@@ -10,7 +9,7 @@ import org.jmock.Expectations;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.briarproject.bramble.test.TestUtils.getAuthor;
|
import static org.briarproject.bramble.test.TestUtils.getAuthor;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||||
import static org.briarproject.briar.api.introduction.IntroductionConstants.LABEL_SESSION_ID;
|
import static org.briarproject.briar.api.introduction.IntroductionConstants.LABEL_SESSION_ID;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
@@ -25,7 +24,7 @@ public class IntroductionCryptoTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
private final Author introducer = getAuthor();
|
private final Author introducer = getAuthor();
|
||||||
private final Author alice = getAuthor(), bob = getAuthor();
|
private final Author alice = getAuthor(), bob = getAuthor();
|
||||||
private final byte[] hash = getRandomBytes(UniqueId.LENGTH);
|
private final byte[] hash = getRandomId();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetSessionId() {
|
public void testGetSessionId() {
|
||||||
|
|||||||
@@ -634,7 +634,7 @@ public class IntroductionIntegrationTest
|
|||||||
|
|
||||||
// fake a second ACCEPT message from introducee1
|
// fake a second ACCEPT message from introducee1
|
||||||
Message msg = c1.getMessageEncoder()
|
Message msg = c1.getMessageEncoder()
|
||||||
.encodeAcceptMessage(m.getGroupId(), clock.currentTimeMillis(),
|
.encodeAcceptMessage(m.getGroupId(), m.getTimestamp() + 1,
|
||||||
m.getMessageId(), m.getSessionId(),
|
m.getMessageId(), m.getSessionId(),
|
||||||
m.getEphemeralPublicKey(), m.getAcceptTimestamp(),
|
m.getEphemeralPublicKey(), m.getAcceptTimestamp(),
|
||||||
m.getTransportProperties());
|
m.getTransportProperties());
|
||||||
@@ -671,7 +671,7 @@ public class IntroductionIntegrationTest
|
|||||||
|
|
||||||
// fake a second DECLINE message also from introducee1
|
// fake a second DECLINE message also from introducee1
|
||||||
Message msg = c1.getMessageEncoder()
|
Message msg = c1.getMessageEncoder()
|
||||||
.encodeDeclineMessage(m.getGroupId(), clock.currentTimeMillis(),
|
.encodeDeclineMessage(m.getGroupId(), m.getTimestamp() + 1,
|
||||||
m.getMessageId(), m.getSessionId());
|
m.getMessageId(), m.getSessionId());
|
||||||
c1.getClientHelper().addLocalMessage(msg, new BdfDictionary(), true);
|
c1.getClientHelper().addLocalMessage(msg, new BdfDictionary(), true);
|
||||||
|
|
||||||
@@ -715,7 +715,7 @@ public class IntroductionIntegrationTest
|
|||||||
|
|
||||||
// fake a second AUTH message also from introducee1
|
// fake a second AUTH message also from introducee1
|
||||||
Message msg = c1.getMessageEncoder()
|
Message msg = c1.getMessageEncoder()
|
||||||
.encodeAuthMessage(m.getGroupId(), clock.currentTimeMillis(),
|
.encodeAuthMessage(m.getGroupId(), m.getTimestamp() + 1,
|
||||||
m.getMessageId(), m.getSessionId(), m.getMac(),
|
m.getMessageId(), m.getSessionId(), m.getMac(),
|
||||||
m.getSignature());
|
m.getSignature());
|
||||||
c1.getClientHelper().addLocalMessage(msg, new BdfDictionary(), true);
|
c1.getClientHelper().addLocalMessage(msg, new BdfDictionary(), true);
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ interface IntroductionIntegrationTestComponent
|
|||||||
|
|
||||||
void inject(IntroductionIntegrationTest init);
|
void inject(IntroductionIntegrationTest init);
|
||||||
|
|
||||||
|
void inject(MessageEncoderParserIntegrationTest init);
|
||||||
|
void inject(SessionEncoderParserIntegrationTest init);
|
||||||
|
void inject(IntroductionCryptoIntegrationTest init);
|
||||||
|
|
||||||
MessageEncoder getMessageEncoder();
|
MessageEncoder getMessageEncoder();
|
||||||
MessageParser getMessageParser();
|
MessageParser getMessageParser();
|
||||||
SessionParser getSessionParser();
|
SessionParser getSessionParser();
|
||||||
|
|||||||
@@ -126,8 +126,8 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
|||||||
previousMsgId.getBytes(), getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
|
previousMsgId.getBytes(), getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
|
||||||
acceptTimestamp, transportProperties);
|
acceptTimestamp, transportProperties);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(clientHelper).parseAndValidateTransportProperties(
|
oneOf(clientHelper).parseAndValidateTransportPropertiesMap(
|
||||||
transportProperties.getDictionary("transportId"));
|
transportProperties);
|
||||||
}});
|
}});
|
||||||
expectEncodeMetadata(ACCEPT);
|
expectEncodeMetadata(ACCEPT);
|
||||||
BdfMessageContext messageContext =
|
BdfMessageContext messageContext =
|
||||||
@@ -178,6 +178,14 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
|||||||
validator.validateMessage(message, group, body);
|
validator.validateMessage(message, group, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = FormatException.class)
|
||||||
|
public void testRejectsNegativeTimestampForAccept() throws Exception {
|
||||||
|
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
||||||
|
previousMsgId.getBytes(), getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
|
||||||
|
-1, transportProperties);
|
||||||
|
validator.validateMessage(message, group, body);
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testRejectsEmptyTransportPropertiesForAccept()
|
public void testRejectsEmptyTransportPropertiesForAccept()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -405,9 +413,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
|||||||
|
|
||||||
private void expectEncodeRequestMetadata() {
|
private void expectEncodeRequestMetadata() {
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(messageEncoder)
|
oneOf(messageEncoder).encodeRequestMetadata(message.getTimestamp());
|
||||||
.encodeRequestMetadata(message.getTimestamp(), false, false,
|
|
||||||
false);
|
|
||||||
will(returnValue(meta));
|
will(returnValue(meta));
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ import org.briarproject.bramble.api.sync.MessageId;
|
|||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.briar.api.client.SessionId;
|
import org.briarproject.briar.api.client.SessionId;
|
||||||
import org.briarproject.briar.test.BriarIntegrationTestComponent;
|
|
||||||
import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -72,8 +70,8 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
|||||||
private final byte[] signature = getRandomBytes(MAX_SIGNATURE_BYTES);
|
private final byte[] signature = getRandomBytes(MAX_SIGNATURE_BYTES);
|
||||||
|
|
||||||
public MessageEncoderParserIntegrationTest() {
|
public MessageEncoderParserIntegrationTest() {
|
||||||
BriarIntegrationTestComponent component =
|
IntroductionIntegrationTestComponent component =
|
||||||
DaggerBriarIntegrationTestComponent.builder().build();
|
DaggerIntroductionIntegrationTestComponent.builder().build();
|
||||||
component.inject(this);
|
component.inject(this);
|
||||||
|
|
||||||
messageEncoder = new MessageEncoderImpl(clientHelper, messageFactory);
|
messageEncoder = new MessageEncoderImpl(clientHelper, messageFactory);
|
||||||
@@ -86,13 +84,13 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testRequestMessageMetadata() throws FormatException {
|
public void testRequestMessageMetadata() throws FormatException {
|
||||||
BdfDictionary d = messageEncoder
|
BdfDictionary d = messageEncoder
|
||||||
.encodeRequestMetadata(timestamp, true, false, false);
|
.encodeRequestMetadata(timestamp);
|
||||||
MessageMetadata meta = messageParser.parseMetadata(d);
|
MessageMetadata meta = messageParser.parseMetadata(d);
|
||||||
|
|
||||||
assertEquals(REQUEST, meta.getMessageType());
|
assertEquals(REQUEST, meta.getMessageType());
|
||||||
assertNull(meta.getSessionId());
|
assertNull(meta.getSessionId());
|
||||||
assertEquals(timestamp, meta.getTimestamp());
|
assertEquals(timestamp, meta.getTimestamp());
|
||||||
assertTrue(meta.isLocal());
|
assertFalse(meta.isLocal());
|
||||||
assertFalse(meta.isRead());
|
assertFalse(meta.isRead());
|
||||||
assertFalse(meta.isVisibleInConversation());
|
assertFalse(meta.isVisibleInConversation());
|
||||||
assertFalse(meta.isAvailableToAnswer());
|
assertFalse(meta.isAvailableToAnswer());
|
||||||
|
|||||||
@@ -7,13 +7,12 @@ import org.briarproject.bramble.api.identity.Author;
|
|||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
import org.briarproject.bramble.api.sync.Message;
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
import org.briarproject.bramble.api.sync.MessageFactory;
|
import org.briarproject.bramble.api.sync.MessageFactory;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
|
||||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.briarproject.bramble.test.TestUtils.getAuthor;
|
import static org.briarproject.bramble.test.TestUtils.getAuthor;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
import static org.briarproject.bramble.test.TestUtils.getMessage;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||||
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||||
import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_REQUEST_MESSAGE_LENGTH;
|
import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_REQUEST_MESSAGE_LENGTH;
|
||||||
@@ -28,11 +27,9 @@ public class MessageEncoderTest extends BrambleMockTestCase {
|
|||||||
new MessageEncoderImpl(clientHelper, messageFactory);
|
new MessageEncoderImpl(clientHelper, messageFactory);
|
||||||
|
|
||||||
private final GroupId groupId = new GroupId(getRandomId());
|
private final GroupId groupId = new GroupId(getRandomId());
|
||||||
private final long timestamp = 42L;
|
private final Message message = getMessage(groupId);
|
||||||
private final Message message =
|
private final long timestamp = message.getTimestamp();
|
||||||
new Message(new MessageId(getRandomId()), groupId, timestamp,
|
private final byte[] body = message.getRaw();
|
||||||
getRandomBytes(48));
|
|
||||||
private final byte[] body = getRandomBytes(42);
|
|
||||||
private final Author author = getAuthor();
|
private final Author author = getAuthor();
|
||||||
private final BdfList authorList = new BdfList();
|
private final BdfList authorList = new BdfList();
|
||||||
private final String text = getRandomString(MAX_REQUEST_MESSAGE_LENGTH);
|
private final String text = getRandomString(MAX_REQUEST_MESSAGE_LENGTH);
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ import org.briarproject.bramble.api.transport.KeySetId;
|
|||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.briar.api.client.SessionId;
|
import org.briarproject.briar.api.client.SessionId;
|
||||||
import org.briarproject.briar.introduction.IntroducerSession.Introducee;
|
import org.briarproject.briar.introduction.IntroducerSession.Introducee;
|
||||||
import org.briarproject.briar.test.BriarIntegrationTestComponent;
|
|
||||||
import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -82,8 +80,8 @@ public class SessionEncoderParserIntegrationTest extends BrambleTestCase {
|
|||||||
private final byte[] remoteMacKey = getRandomBytes(SecretKey.LENGTH);
|
private final byte[] remoteMacKey = getRandomBytes(SecretKey.LENGTH);
|
||||||
|
|
||||||
public SessionEncoderParserIntegrationTest() {
|
public SessionEncoderParserIntegrationTest() {
|
||||||
BriarIntegrationTestComponent component =
|
IntroductionIntegrationTestComponent component =
|
||||||
DaggerBriarIntegrationTestComponent.builder().build();
|
DaggerIntroductionIntegrationTestComponent.builder().build();
|
||||||
component.inject(this);
|
component.inject(this);
|
||||||
|
|
||||||
sessionEncoder = new SessionEncoderImpl(clientHelper);
|
sessionEncoder = new SessionEncoderImpl(clientHelper);
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import org.briarproject.bramble.api.identity.IdentityManager;
|
|||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.bramble.api.properties.TransportPropertyManager;
|
import org.briarproject.bramble.api.properties.TransportPropertyManager;
|
||||||
import org.briarproject.bramble.api.sync.SyncSessionFactory;
|
import org.briarproject.bramble.api.sync.SyncSessionFactory;
|
||||||
import org.briarproject.bramble.api.transport.KeyManager;
|
|
||||||
import org.briarproject.bramble.client.ClientModule;
|
import org.briarproject.bramble.client.ClientModule;
|
||||||
import org.briarproject.bramble.contact.ContactModule;
|
import org.briarproject.bramble.contact.ContactModule;
|
||||||
import org.briarproject.bramble.crypto.CryptoModule;
|
import org.briarproject.bramble.crypto.CryptoModule;
|
||||||
@@ -37,8 +36,8 @@ import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager
|
|||||||
import org.briarproject.briar.blog.BlogModule;
|
import org.briarproject.briar.blog.BlogModule;
|
||||||
import org.briarproject.briar.client.BriarClientModule;
|
import org.briarproject.briar.client.BriarClientModule;
|
||||||
import org.briarproject.briar.forum.ForumModule;
|
import org.briarproject.briar.forum.ForumModule;
|
||||||
|
import org.briarproject.briar.introduction.IntroductionCryptoIntegrationTest;
|
||||||
import org.briarproject.briar.introduction.IntroductionModule;
|
import org.briarproject.briar.introduction.IntroductionModule;
|
||||||
import org.briarproject.briar.introduction.IntroductionCryptoImplTest;
|
|
||||||
import org.briarproject.briar.introduction.MessageEncoderParserIntegrationTest;
|
import org.briarproject.briar.introduction.MessageEncoderParserIntegrationTest;
|
||||||
import org.briarproject.briar.introduction.SessionEncoderParserIntegrationTest;
|
import org.briarproject.briar.introduction.SessionEncoderParserIntegrationTest;
|
||||||
import org.briarproject.briar.messaging.MessagingModule;
|
import org.briarproject.briar.messaging.MessagingModule;
|
||||||
@@ -80,10 +79,6 @@ public interface BriarIntegrationTestComponent {
|
|||||||
|
|
||||||
void inject(BriarIntegrationTest<BriarIntegrationTestComponent> init);
|
void inject(BriarIntegrationTest<BriarIntegrationTestComponent> init);
|
||||||
|
|
||||||
void inject(MessageEncoderParserIntegrationTest init);
|
|
||||||
void inject(SessionEncoderParserIntegrationTest init);
|
|
||||||
void inject(IntroductionCryptoImplTest init);
|
|
||||||
|
|
||||||
void inject(BlogModule.EagerSingletons init);
|
void inject(BlogModule.EagerSingletons init);
|
||||||
|
|
||||||
void inject(ContactModule.EagerSingletons init);
|
void inject(ContactModule.EagerSingletons init);
|
||||||
@@ -146,8 +141,6 @@ public interface BriarIntegrationTestComponent {
|
|||||||
|
|
||||||
TransportPropertyManager getTransportPropertyManager();
|
TransportPropertyManager getTransportPropertyManager();
|
||||||
|
|
||||||
KeyManager getKeyManager();
|
|
||||||
|
|
||||||
AuthorFactory getAuthorFactory();
|
AuthorFactory getAuthorFactory();
|
||||||
|
|
||||||
BlogFactory getBlogFactory();
|
BlogFactory getBlogFactory();
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package org.briarproject.briar.test;
|
package org.briarproject.briar.test;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
|
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.identity.Author;
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
import org.briarproject.bramble.api.identity.AuthorFactory;
|
import org.briarproject.bramble.api.identity.AuthorFactory;
|
||||||
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
import org.briarproject.briar.api.client.MessageTracker;
|
import org.briarproject.briar.api.client.MessageTracker;
|
||||||
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
||||||
@@ -35,4 +38,12 @@ public class BriarTestUtils {
|
|||||||
getRandomBytes(MAX_PUBLIC_KEY_LENGTH));
|
getRandomBytes(MAX_PUBLIC_KEY_LENGTH));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static LocalAuthor getRealLocalAuthor(
|
||||||
|
CryptoComponent cryptoComponent, AuthorFactory authorFactory) {
|
||||||
|
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair();
|
||||||
|
return authorFactory.createLocalAuthor(getRandomString(5),
|
||||||
|
keyPair.getPublic().getEncoded(),
|
||||||
|
keyPair.getPrivate().getEncoded());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user