mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-15 20:29:52 +01:00
Merge branch '617-crypto-labels' into 'master'
Use namespaced labels for all crypto operations See merge request !632
This commit is contained in:
@@ -141,8 +141,9 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
|
||||
}
|
||||
|
||||
// Derive the header keys for the transport streams
|
||||
SecretKey aliceHeaderKey = crypto.deriveHeaderKey(masterSecret, true);
|
||||
SecretKey bobHeaderKey = crypto.deriveHeaderKey(masterSecret, false);
|
||||
SecretKey aliceHeaderKey = crypto.deriveKey(ALICE_KEY_LABEL,
|
||||
masterSecret);
|
||||
SecretKey bobHeaderKey = crypto.deriveKey(BOB_KEY_LABEL, masterSecret);
|
||||
|
||||
// Create the readers
|
||||
InputStream streamReader =
|
||||
@@ -156,8 +157,8 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
|
||||
BdfWriter w = bdfWriterFactory.createWriter(streamWriter);
|
||||
|
||||
// Derive the nonces to be signed
|
||||
byte[] aliceNonce = crypto.deriveSignatureNonce(masterSecret, true);
|
||||
byte[] bobNonce = crypto.deriveSignatureNonce(masterSecret, false);
|
||||
byte[] aliceNonce = crypto.mac(ALICE_NONCE_LABEL, masterSecret);
|
||||
byte[] bobNonce = crypto.mac(BOB_NONCE_LABEL, masterSecret);
|
||||
|
||||
// Exchange pseudonyms, signed nonces, and timestamps
|
||||
long localTimestamp = clock.currentTimeMillis();
|
||||
@@ -312,8 +313,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
|
||||
return contactId;
|
||||
}
|
||||
|
||||
private void tryToClose(DuplexTransportConnection conn,
|
||||
boolean exception) {
|
||||
private void tryToClose(DuplexTransportConnection conn, boolean exception) {
|
||||
try {
|
||||
LOG.info("Closing connection");
|
||||
conn.getReader().dispose(exception, true);
|
||||
|
||||
@@ -10,11 +10,7 @@ import org.briarproject.bramble.api.crypto.KeyParser;
|
||||
import org.briarproject.bramble.api.crypto.PrivateKey;
|
||||
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.plugin.TransportId;
|
||||
import org.briarproject.bramble.api.system.SecureRandomProvider;
|
||||
import org.briarproject.bramble.api.transport.IncomingKeys;
|
||||
import org.briarproject.bramble.api.transport.OutgoingKeys;
|
||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||
import org.briarproject.bramble.util.ByteUtils;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
|
||||
@@ -30,7 +26,6 @@ import org.spongycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.spongycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.spongycastle.crypto.params.KeyParameter;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Provider;
|
||||
@@ -44,14 +39,8 @@ import java.util.logging.Logger;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
|
||||
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static org.briarproject.bramble.crypto.EllipticCurveConstants.PARAMETERS;
|
||||
import static org.briarproject.bramble.util.ByteUtils.INT_16_BYTES;
|
||||
import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
|
||||
import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES;
|
||||
import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
|
||||
import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||
|
||||
class CryptoComponentImpl implements CryptoComponent {
|
||||
|
||||
@@ -65,39 +54,6 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
private static final int PBKDF_SALT_BYTES = 32; // 256 bits
|
||||
private static final int PBKDF_TARGET_MILLIS = 500;
|
||||
private static final int PBKDF_SAMPLES = 30;
|
||||
private static final int HASH_SIZE = 256 / 8;
|
||||
|
||||
private static byte[] ascii(String s) {
|
||||
return s.getBytes(Charset.forName("US-ASCII"));
|
||||
}
|
||||
|
||||
// KDF labels for contact exchange stream header key derivation
|
||||
private static final byte[] A_INVITE = ascii("ALICE_INVITATION_KEY");
|
||||
private static final byte[] B_INVITE = ascii("BOB_INVITATION_KEY");
|
||||
// KDF labels for contact exchange signature nonce derivation
|
||||
private static final byte[] A_SIG_NONCE = ascii("ALICE_SIGNATURE_NONCE");
|
||||
private static final byte[] B_SIG_NONCE = ascii("BOB_SIGNATURE_NONCE");
|
||||
// Hash label for BQP public key commitment derivation
|
||||
private static final String COMMIT =
|
||||
"org.briarproject.bramble.COMMIT";
|
||||
// Hash label for shared secret derivation
|
||||
private static final String SHARED_SECRET =
|
||||
"org.briarproject.bramble.SHARED_SECRET";
|
||||
// KDF label for BQP confirmation key derivation
|
||||
private static final byte[] CONFIRMATION_KEY = ascii("CONFIRMATION_KEY");
|
||||
// KDF label for master key derivation
|
||||
private static final byte[] MASTER_KEY = ascii("MASTER_KEY");
|
||||
// KDF labels for tag key derivation
|
||||
private static final byte[] A_TAG = ascii("ALICE_TAG_KEY");
|
||||
private static final byte[] B_TAG = ascii("BOB_TAG_KEY");
|
||||
// KDF labels for header key derivation
|
||||
private static final byte[] A_HEADER = ascii("ALICE_HEADER_KEY");
|
||||
private static final byte[] B_HEADER = ascii("BOB_HEADER_KEY");
|
||||
// KDF labels for MAC key derivation
|
||||
private static final byte[] A_MAC = ascii("ALICE_MAC_KEY");
|
||||
private static final byte[] B_MAC = ascii("BOB_MAC_KEY");
|
||||
// KDF label for key rotation
|
||||
private static final byte[] ROTATE = ascii("ROTATE");
|
||||
|
||||
private final SecureRandom secureRandom;
|
||||
private final ECKeyPairGenerator agreementKeyPairGenerator;
|
||||
@@ -263,179 +219,26 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretKey deriveHeaderKey(SecretKey master,
|
||||
boolean alice) {
|
||||
return new SecretKey(macKdf(master, alice ? A_INVITE : B_INVITE));
|
||||
public SecretKey deriveKey(String label, SecretKey k, byte[]... inputs) {
|
||||
byte[] mac = mac(label, k, inputs);
|
||||
if (mac.length != SecretKey.LENGTH) throw new IllegalStateException();
|
||||
return new SecretKey(mac);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretKey deriveMacKey(SecretKey master, boolean alice) {
|
||||
return new SecretKey(macKdf(master, alice ? A_MAC : B_MAC));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] deriveSignatureNonce(SecretKey master,
|
||||
boolean alice) {
|
||||
return macKdf(master, alice ? A_SIG_NONCE : B_SIG_NONCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] deriveKeyCommitment(byte[] publicKey) {
|
||||
byte[] hash = hash(COMMIT, publicKey);
|
||||
// The output is the first COMMIT_LENGTH bytes of the hash
|
||||
byte[] commitment = new byte[COMMIT_LENGTH];
|
||||
System.arraycopy(hash, 0, commitment, 0, COMMIT_LENGTH);
|
||||
return commitment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretKey deriveSharedSecret(byte[] theirPublicKey,
|
||||
public SecretKey deriveSharedSecret(String label, PublicKey theirPublicKey,
|
||||
KeyPair ourKeyPair, boolean alice) throws GeneralSecurityException {
|
||||
PrivateKey ourPriv = ourKeyPair.getPrivate();
|
||||
PublicKey theirPub = agreementKeyParser.parsePublicKey(theirPublicKey);
|
||||
byte[] raw = performRawKeyAgreement(ourPriv, theirPub);
|
||||
byte[] raw = performRawKeyAgreement(ourPriv, theirPublicKey);
|
||||
byte[] alicePub, bobPub;
|
||||
if (alice) {
|
||||
alicePub = ourKeyPair.getPublic().getEncoded();
|
||||
bobPub = theirPublicKey;
|
||||
bobPub = theirPublicKey.getEncoded();
|
||||
} else {
|
||||
alicePub = theirPublicKey;
|
||||
alicePub = theirPublicKey.getEncoded();
|
||||
bobPub = ourKeyPair.getPublic().getEncoded();
|
||||
}
|
||||
return new SecretKey(hash(SHARED_SECRET, raw, alicePub, bobPub));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] deriveConfirmationRecord(SecretKey sharedSecret,
|
||||
byte[] theirPayload, byte[] ourPayload, byte[] theirPublicKey,
|
||||
KeyPair ourKeyPair, boolean alice, boolean aliceRecord) {
|
||||
SecretKey ck = new SecretKey(macKdf(sharedSecret, CONFIRMATION_KEY));
|
||||
byte[] alicePayload, alicePub, bobPayload, bobPub;
|
||||
if (alice) {
|
||||
alicePayload = ourPayload;
|
||||
alicePub = ourKeyPair.getPublic().getEncoded();
|
||||
bobPayload = theirPayload;
|
||||
bobPub = theirPublicKey;
|
||||
} else {
|
||||
alicePayload = theirPayload;
|
||||
alicePub = theirPublicKey;
|
||||
bobPayload = ourPayload;
|
||||
bobPub = ourKeyPair.getPublic().getEncoded();
|
||||
}
|
||||
if (aliceRecord)
|
||||
return macKdf(ck, alicePayload, alicePub, bobPayload, bobPub);
|
||||
else
|
||||
return macKdf(ck, bobPayload, bobPub, alicePayload, alicePub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretKey deriveMasterSecret(SecretKey sharedSecret) {
|
||||
return new SecretKey(macKdf(sharedSecret, MASTER_KEY));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretKey deriveMasterSecret(byte[] theirPublicKey,
|
||||
KeyPair ourKeyPair, boolean alice) throws GeneralSecurityException {
|
||||
return deriveMasterSecret(deriveSharedSecret(
|
||||
theirPublicKey, ourKeyPair, alice));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportKeys deriveTransportKeys(TransportId t,
|
||||
SecretKey master, long rotationPeriod, boolean alice) {
|
||||
// Keys for the previous period are derived from the master secret
|
||||
SecretKey inTagPrev = deriveTagKey(master, t, !alice);
|
||||
SecretKey inHeaderPrev = deriveHeaderKey(master, t, !alice);
|
||||
SecretKey outTagPrev = deriveTagKey(master, t, alice);
|
||||
SecretKey outHeaderPrev = deriveHeaderKey(master, t, alice);
|
||||
// Derive the keys for the current and next periods
|
||||
SecretKey inTagCurr = rotateKey(inTagPrev, rotationPeriod);
|
||||
SecretKey inHeaderCurr = rotateKey(inHeaderPrev, rotationPeriod);
|
||||
SecretKey inTagNext = rotateKey(inTagCurr, rotationPeriod + 1);
|
||||
SecretKey inHeaderNext = rotateKey(inHeaderCurr, rotationPeriod + 1);
|
||||
SecretKey outTagCurr = rotateKey(outTagPrev, rotationPeriod);
|
||||
SecretKey outHeaderCurr = rotateKey(outHeaderPrev, rotationPeriod);
|
||||
// Initialise the reordering windows and stream counters
|
||||
IncomingKeys inPrev = new IncomingKeys(inTagPrev, inHeaderPrev,
|
||||
rotationPeriod - 1);
|
||||
IncomingKeys inCurr = new IncomingKeys(inTagCurr, inHeaderCurr,
|
||||
rotationPeriod);
|
||||
IncomingKeys inNext = new IncomingKeys(inTagNext, inHeaderNext,
|
||||
rotationPeriod + 1);
|
||||
OutgoingKeys outCurr = new OutgoingKeys(outTagCurr, outHeaderCurr,
|
||||
rotationPeriod);
|
||||
// Collect and return the keys
|
||||
return new TransportKeys(t, inPrev, inCurr, inNext, outCurr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportKeys rotateTransportKeys(TransportKeys k,
|
||||
long rotationPeriod) {
|
||||
if (k.getRotationPeriod() >= rotationPeriod) return k;
|
||||
IncomingKeys inPrev = k.getPreviousIncomingKeys();
|
||||
IncomingKeys inCurr = k.getCurrentIncomingKeys();
|
||||
IncomingKeys inNext = k.getNextIncomingKeys();
|
||||
OutgoingKeys outCurr = k.getCurrentOutgoingKeys();
|
||||
long startPeriod = outCurr.getRotationPeriod();
|
||||
// Rotate the keys
|
||||
for (long p = startPeriod + 1; p <= rotationPeriod; p++) {
|
||||
inPrev = inCurr;
|
||||
inCurr = inNext;
|
||||
SecretKey inNextTag = rotateKey(inNext.getTagKey(), p + 1);
|
||||
SecretKey inNextHeader = rotateKey(inNext.getHeaderKey(), p + 1);
|
||||
inNext = new IncomingKeys(inNextTag, inNextHeader, p + 1);
|
||||
SecretKey outCurrTag = rotateKey(outCurr.getTagKey(), p);
|
||||
SecretKey outCurrHeader = rotateKey(outCurr.getHeaderKey(), p);
|
||||
outCurr = new OutgoingKeys(outCurrTag, outCurrHeader, p);
|
||||
}
|
||||
// Collect and return the keys
|
||||
return new TransportKeys(k.getTransportId(), inPrev, inCurr, inNext,
|
||||
outCurr);
|
||||
}
|
||||
|
||||
private SecretKey rotateKey(SecretKey k, long rotationPeriod) {
|
||||
byte[] period = new byte[INT_64_BYTES];
|
||||
ByteUtils.writeUint64(rotationPeriod, period, 0);
|
||||
return new SecretKey(macKdf(k, ROTATE, period));
|
||||
}
|
||||
|
||||
private SecretKey deriveTagKey(SecretKey master, TransportId t,
|
||||
boolean alice) {
|
||||
byte[] id = StringUtils.toUtf8(t.getString());
|
||||
return new SecretKey(macKdf(master, alice ? A_TAG : B_TAG, id));
|
||||
}
|
||||
|
||||
private SecretKey deriveHeaderKey(SecretKey master, TransportId t,
|
||||
boolean alice) {
|
||||
byte[] id = StringUtils.toUtf8(t.getString());
|
||||
return new SecretKey(macKdf(master, alice ? A_HEADER : B_HEADER, id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encodeTag(byte[] tag, SecretKey tagKey, int protocolVersion,
|
||||
long streamNumber) {
|
||||
if (tag.length < TAG_LENGTH) throw new IllegalArgumentException();
|
||||
if (protocolVersion < 0 || protocolVersion > MAX_16_BIT_UNSIGNED)
|
||||
throw new IllegalArgumentException();
|
||||
if (streamNumber < 0 || streamNumber > MAX_32_BIT_UNSIGNED)
|
||||
throw new IllegalArgumentException();
|
||||
// Initialise the PRF
|
||||
Digest prf = new Blake2sDigest(tagKey.getBytes());
|
||||
// The output of the PRF must be long enough to use as a tag
|
||||
int macLength = prf.getDigestSize();
|
||||
if (macLength < TAG_LENGTH) throw new IllegalStateException();
|
||||
// The input is the protocol version as a 16-bit integer, followed by
|
||||
// the stream number as a 64-bit integer
|
||||
byte[] protocolVersionBytes = new byte[INT_16_BYTES];
|
||||
ByteUtils.writeUint16(protocolVersion, protocolVersionBytes, 0);
|
||||
prf.update(protocolVersionBytes, 0, protocolVersionBytes.length);
|
||||
byte[] streamNumberBytes = new byte[INT_64_BYTES];
|
||||
ByteUtils.writeUint64(streamNumber, streamNumberBytes, 0);
|
||||
prf.update(streamNumberBytes, 0, streamNumberBytes.length);
|
||||
byte[] mac = new byte[macLength];
|
||||
prf.doFinal(mac, 0);
|
||||
// The output is the first TAG_LENGTH bytes of the MAC
|
||||
System.arraycopy(mac, 0, tag, 0, TAG_LENGTH);
|
||||
return new SecretKey(hash(label, raw, alicePub, bobPub));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -513,14 +316,13 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHashLength() {
|
||||
return HASH_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] mac(SecretKey macKey, byte[]... inputs) {
|
||||
public byte[] mac(String label, SecretKey macKey, byte[]... inputs) {
|
||||
byte[] labelBytes = StringUtils.toUtf8(label);
|
||||
Digest mac = new Blake2sDigest(macKey.getBytes());
|
||||
byte[] length = new byte[INT_32_BYTES];
|
||||
ByteUtils.writeUint32(labelBytes.length, length, 0);
|
||||
mac.update(length, 0, length.length);
|
||||
mac.update(labelBytes, 0, labelBytes.length);
|
||||
for (byte[] input : inputs) {
|
||||
ByteUtils.writeUint32(input.length, length, 0);
|
||||
mac.update(length, 0, length.length);
|
||||
@@ -612,30 +414,6 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
return AsciiArmour.wrap(b, lineLength);
|
||||
}
|
||||
|
||||
// Key derivation function based on a pseudo-random function - see
|
||||
// NIST SP 800-108, section 5.1
|
||||
private byte[] macKdf(SecretKey key, byte[]... inputs) {
|
||||
// Initialise the PRF
|
||||
Digest prf = new Blake2sDigest(key.getBytes());
|
||||
// The output of the PRF must be long enough to use as a key
|
||||
int macLength = prf.getDigestSize();
|
||||
if (macLength < SecretKey.LENGTH) throw new IllegalStateException();
|
||||
// Calculate the PRF over the concatenated length-prefixed inputs
|
||||
byte[] length = new byte[INT_32_BYTES];
|
||||
for (byte[] input : inputs) {
|
||||
ByteUtils.writeUint32(input.length, length, 0);
|
||||
prf.update(length, 0, length.length);
|
||||
prf.update(input, 0, input.length);
|
||||
}
|
||||
byte[] mac = new byte[macLength];
|
||||
prf.doFinal(mac, 0);
|
||||
// The output is the first SecretKey.LENGTH bytes of the MAC
|
||||
if (mac.length == SecretKey.LENGTH) return mac;
|
||||
byte[] truncated = new byte[SecretKey.LENGTH];
|
||||
System.arraycopy(mac, 0, truncated, 0, truncated.length);
|
||||
return truncated;
|
||||
}
|
||||
|
||||
// Password-based key derivation function - see PKCS#5 v2.1, section 5.2
|
||||
private byte[] pbkdf2(String password, byte[] salt, int iterations) {
|
||||
byte[] utf8 = StringUtils.toUtf8(password);
|
||||
|
||||
@@ -3,9 +3,11 @@ package org.briarproject.bramble.crypto;
|
||||
import org.briarproject.bramble.TimeLoggingExecutor;
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||
import org.briarproject.bramble.api.crypto.KeyAgreementCrypto;
|
||||
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
|
||||
import org.briarproject.bramble.api.crypto.StreamDecrypterFactory;
|
||||
import org.briarproject.bramble.api.crypto.StreamEncrypterFactory;
|
||||
import org.briarproject.bramble.api.crypto.TransportCrypto;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.system.SecureRandomProvider;
|
||||
|
||||
@@ -74,6 +76,12 @@ public class CryptoModule {
|
||||
return new PasswordStrengthEstimatorImpl();
|
||||
}
|
||||
|
||||
@Provides
|
||||
TransportCrypto provideTransportCrypto(
|
||||
TransportCryptoImpl transportCrypto) {
|
||||
return transportCrypto;
|
||||
}
|
||||
|
||||
@Provides
|
||||
StreamDecrypterFactory provideStreamDecrypterFactory(
|
||||
Provider<AuthenticatedCipher> cipherProvider) {
|
||||
@@ -81,9 +89,17 @@ public class CryptoModule {
|
||||
}
|
||||
|
||||
@Provides
|
||||
StreamEncrypterFactory provideStreamEncrypterFactory(CryptoComponent crypto,
|
||||
StreamEncrypterFactory provideStreamEncrypterFactory(
|
||||
CryptoComponent crypto, TransportCrypto transportCrypto,
|
||||
Provider<AuthenticatedCipher> cipherProvider) {
|
||||
return new StreamEncrypterFactoryImpl(crypto, cipherProvider);
|
||||
return new StreamEncrypterFactoryImpl(crypto, transportCrypto,
|
||||
cipherProvider);
|
||||
}
|
||||
|
||||
@Provides
|
||||
KeyAgreementCrypto provideKeyAgreementCrypto(
|
||||
KeyAgreementCryptoImpl keyAgreementCrypto) {
|
||||
return keyAgreementCrypto;
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package org.briarproject.bramble.crypto;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.KeyAgreementCrypto;
|
||||
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
|
||||
|
||||
class KeyAgreementCryptoImpl implements KeyAgreementCrypto {
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
|
||||
@Inject
|
||||
KeyAgreementCryptoImpl(CryptoComponent crypto) {
|
||||
this.crypto = crypto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] deriveKeyCommitment(PublicKey publicKey) {
|
||||
byte[] hash = crypto.hash(COMMIT_LABEL, publicKey.getEncoded());
|
||||
// The output is the first COMMIT_LENGTH bytes of the hash
|
||||
byte[] commitment = new byte[COMMIT_LENGTH];
|
||||
System.arraycopy(hash, 0, commitment, 0, COMMIT_LENGTH);
|
||||
return commitment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] deriveConfirmationRecord(SecretKey sharedSecret,
|
||||
byte[] theirPayload, byte[] ourPayload, PublicKey theirPublicKey,
|
||||
KeyPair ourKeyPair, boolean alice, boolean aliceRecord) {
|
||||
SecretKey ck = crypto.deriveKey(CONFIRMATION_KEY_LABEL, sharedSecret);
|
||||
byte[] alicePayload, alicePub, bobPayload, bobPub;
|
||||
if (alice) {
|
||||
alicePayload = ourPayload;
|
||||
alicePub = ourKeyPair.getPublic().getEncoded();
|
||||
bobPayload = theirPayload;
|
||||
bobPub = theirPublicKey.getEncoded();
|
||||
} else {
|
||||
alicePayload = theirPayload;
|
||||
alicePub = theirPublicKey.getEncoded();
|
||||
bobPayload = ourPayload;
|
||||
bobPub = ourKeyPair.getPublic().getEncoded();
|
||||
}
|
||||
if (aliceRecord) {
|
||||
return crypto.mac(CONFIRMATION_MAC_LABEL, ck, alicePayload,
|
||||
alicePub, bobPayload, bobPub);
|
||||
} else {
|
||||
return crypto.mac(CONFIRMATION_MAC_LABEL, ck, bobPayload, bobPub,
|
||||
alicePayload, alicePub);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.crypto.StreamEncrypter;
|
||||
import org.briarproject.bramble.api.crypto.StreamEncrypterFactory;
|
||||
import org.briarproject.bramble.api.crypto.TransportCrypto;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.transport.StreamContext;
|
||||
|
||||
@@ -22,12 +23,15 @@ import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENG
|
||||
class StreamEncrypterFactoryImpl implements StreamEncrypterFactory {
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
private final TransportCrypto transportCrypto;
|
||||
private final Provider<AuthenticatedCipher> cipherProvider;
|
||||
|
||||
@Inject
|
||||
StreamEncrypterFactoryImpl(CryptoComponent crypto,
|
||||
TransportCrypto transportCrypto,
|
||||
Provider<AuthenticatedCipher> cipherProvider) {
|
||||
this.crypto = crypto;
|
||||
this.transportCrypto = transportCrypto;
|
||||
this.cipherProvider = cipherProvider;
|
||||
}
|
||||
|
||||
@@ -37,7 +41,8 @@ class StreamEncrypterFactoryImpl implements StreamEncrypterFactory {
|
||||
AuthenticatedCipher cipher = cipherProvider.get();
|
||||
long streamNumber = ctx.getStreamNumber();
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
crypto.encodeTag(tag, ctx.getTagKey(), PROTOCOL_VERSION, streamNumber);
|
||||
transportCrypto.encodeTag(tag, ctx.getTagKey(), PROTOCOL_VERSION,
|
||||
streamNumber);
|
||||
byte[] streamHeaderNonce = new byte[STREAM_HEADER_NONCE_LENGTH];
|
||||
crypto.getSecureRandom().nextBytes(streamHeaderNonce);
|
||||
SecretKey frameKey = crypto.generateSecretKey();
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
package org.briarproject.bramble.crypto;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.crypto.TransportCrypto;
|
||||
import org.briarproject.bramble.api.plugin.TransportId;
|
||||
import org.briarproject.bramble.api.transport.IncomingKeys;
|
||||
import org.briarproject.bramble.api.transport.OutgoingKeys;
|
||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||
import org.briarproject.bramble.util.ByteUtils;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.spongycastle.crypto.Digest;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.bramble.api.transport.TransportConstants.ALICE_HEADER_LABEL;
|
||||
import static org.briarproject.bramble.api.transport.TransportConstants.ALICE_TAG_LABEL;
|
||||
import static org.briarproject.bramble.api.transport.TransportConstants.BOB_HEADER_LABEL;
|
||||
import static org.briarproject.bramble.api.transport.TransportConstants.BOB_TAG_LABEL;
|
||||
import static org.briarproject.bramble.api.transport.TransportConstants.ROTATE_LABEL;
|
||||
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static org.briarproject.bramble.util.ByteUtils.INT_16_BYTES;
|
||||
import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES;
|
||||
import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
|
||||
import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||
|
||||
class TransportCryptoImpl implements TransportCrypto {
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
|
||||
@Inject
|
||||
TransportCryptoImpl(CryptoComponent crypto) {
|
||||
this.crypto = crypto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportKeys deriveTransportKeys(TransportId t,
|
||||
SecretKey master, long rotationPeriod, boolean alice) {
|
||||
// Keys for the previous period are derived from the master secret
|
||||
SecretKey inTagPrev = deriveTagKey(master, t, !alice);
|
||||
SecretKey inHeaderPrev = deriveHeaderKey(master, t, !alice);
|
||||
SecretKey outTagPrev = deriveTagKey(master, t, alice);
|
||||
SecretKey outHeaderPrev = deriveHeaderKey(master, t, alice);
|
||||
// Derive the keys for the current and next periods
|
||||
SecretKey inTagCurr = rotateKey(inTagPrev, rotationPeriod);
|
||||
SecretKey inHeaderCurr = rotateKey(inHeaderPrev, rotationPeriod);
|
||||
SecretKey inTagNext = rotateKey(inTagCurr, rotationPeriod + 1);
|
||||
SecretKey inHeaderNext = rotateKey(inHeaderCurr, rotationPeriod + 1);
|
||||
SecretKey outTagCurr = rotateKey(outTagPrev, rotationPeriod);
|
||||
SecretKey outHeaderCurr = rotateKey(outHeaderPrev, rotationPeriod);
|
||||
// Initialise the reordering windows and stream counters
|
||||
IncomingKeys inPrev = new IncomingKeys(inTagPrev, inHeaderPrev,
|
||||
rotationPeriod - 1);
|
||||
IncomingKeys inCurr = new IncomingKeys(inTagCurr, inHeaderCurr,
|
||||
rotationPeriod);
|
||||
IncomingKeys inNext = new IncomingKeys(inTagNext, inHeaderNext,
|
||||
rotationPeriod + 1);
|
||||
OutgoingKeys outCurr = new OutgoingKeys(outTagCurr, outHeaderCurr,
|
||||
rotationPeriod);
|
||||
// Collect and return the keys
|
||||
return new TransportKeys(t, inPrev, inCurr, inNext, outCurr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportKeys rotateTransportKeys(TransportKeys k,
|
||||
long rotationPeriod) {
|
||||
if (k.getRotationPeriod() >= rotationPeriod) return k;
|
||||
IncomingKeys inPrev = k.getPreviousIncomingKeys();
|
||||
IncomingKeys inCurr = k.getCurrentIncomingKeys();
|
||||
IncomingKeys inNext = k.getNextIncomingKeys();
|
||||
OutgoingKeys outCurr = k.getCurrentOutgoingKeys();
|
||||
long startPeriod = outCurr.getRotationPeriod();
|
||||
// Rotate the keys
|
||||
for (long p = startPeriod + 1; p <= rotationPeriod; p++) {
|
||||
inPrev = inCurr;
|
||||
inCurr = inNext;
|
||||
SecretKey inNextTag = rotateKey(inNext.getTagKey(), p + 1);
|
||||
SecretKey inNextHeader = rotateKey(inNext.getHeaderKey(), p + 1);
|
||||
inNext = new IncomingKeys(inNextTag, inNextHeader, p + 1);
|
||||
SecretKey outCurrTag = rotateKey(outCurr.getTagKey(), p);
|
||||
SecretKey outCurrHeader = rotateKey(outCurr.getHeaderKey(), p);
|
||||
outCurr = new OutgoingKeys(outCurrTag, outCurrHeader, p);
|
||||
}
|
||||
// Collect and return the keys
|
||||
return new TransportKeys(k.getTransportId(), inPrev, inCurr, inNext,
|
||||
outCurr);
|
||||
}
|
||||
|
||||
private SecretKey rotateKey(SecretKey k, long rotationPeriod) {
|
||||
byte[] period = new byte[INT_64_BYTES];
|
||||
ByteUtils.writeUint64(rotationPeriod, period, 0);
|
||||
return crypto.deriveKey(ROTATE_LABEL, k, period);
|
||||
}
|
||||
|
||||
private SecretKey deriveTagKey(SecretKey master, TransportId t,
|
||||
boolean alice) {
|
||||
String label = alice ? ALICE_TAG_LABEL : BOB_TAG_LABEL;
|
||||
byte[] id = StringUtils.toUtf8(t.getString());
|
||||
return crypto.deriveKey(label, master, id);
|
||||
}
|
||||
|
||||
private SecretKey deriveHeaderKey(SecretKey master, TransportId t,
|
||||
boolean alice) {
|
||||
String label = alice ? ALICE_HEADER_LABEL : BOB_HEADER_LABEL;
|
||||
byte[] id = StringUtils.toUtf8(t.getString());
|
||||
return crypto.deriveKey(label, master, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encodeTag(byte[] tag, SecretKey tagKey, int protocolVersion,
|
||||
long streamNumber) {
|
||||
if (tag.length < TAG_LENGTH) throw new IllegalArgumentException();
|
||||
if (protocolVersion < 0 || protocolVersion > MAX_16_BIT_UNSIGNED)
|
||||
throw new IllegalArgumentException();
|
||||
if (streamNumber < 0 || streamNumber > MAX_32_BIT_UNSIGNED)
|
||||
throw new IllegalArgumentException();
|
||||
// Initialise the PRF
|
||||
Digest prf = new Blake2sDigest(tagKey.getBytes());
|
||||
// The output of the PRF must be long enough to use as a tag
|
||||
int macLength = prf.getDigestSize();
|
||||
if (macLength < TAG_LENGTH) throw new IllegalStateException();
|
||||
// The input is the protocol version as a 16-bit integer, followed by
|
||||
// the stream number as a 64-bit integer
|
||||
byte[] protocolVersionBytes = new byte[INT_16_BYTES];
|
||||
ByteUtils.writeUint16(protocolVersion, protocolVersionBytes, 0);
|
||||
prf.update(protocolVersionBytes, 0, protocolVersionBytes.length);
|
||||
byte[] streamNumberBytes = new byte[INT_64_BYTES];
|
||||
ByteUtils.writeUint64(streamNumber, streamNumberBytes, 0);
|
||||
prf.update(streamNumberBytes, 0, streamNumberBytes.length);
|
||||
byte[] mac = new byte[macLength];
|
||||
prf.doFinal(mac, 0);
|
||||
// The output is the first TAG_LENGTH bytes of the MAC
|
||||
System.arraycopy(mac, 0, tag, 0, TAG_LENGTH);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package org.briarproject.bramble.keyagreement;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.KeyAgreementCrypto;
|
||||
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||
import org.briarproject.bramble.api.data.BdfList;
|
||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
|
||||
@@ -46,7 +46,7 @@ class KeyAgreementConnector {
|
||||
|
||||
private final Callbacks callbacks;
|
||||
private final Clock clock;
|
||||
private final CryptoComponent crypto;
|
||||
private final KeyAgreementCrypto keyAgreementCrypto;
|
||||
private final PluginManager pluginManager;
|
||||
private final CompletionService<KeyAgreementConnection> connect;
|
||||
|
||||
@@ -58,11 +58,11 @@ class KeyAgreementConnector {
|
||||
private volatile boolean alice = false;
|
||||
|
||||
KeyAgreementConnector(Callbacks callbacks, Clock clock,
|
||||
CryptoComponent crypto, PluginManager pluginManager,
|
||||
KeyAgreementCrypto keyAgreementCrypto, PluginManager pluginManager,
|
||||
Executor ioExecutor) {
|
||||
this.callbacks = callbacks;
|
||||
this.clock = clock;
|
||||
this.crypto = crypto;
|
||||
this.keyAgreementCrypto = keyAgreementCrypto;
|
||||
this.pluginManager = pluginManager;
|
||||
connect = new ExecutorCompletionService<>(ioExecutor);
|
||||
}
|
||||
@@ -70,8 +70,8 @@ class KeyAgreementConnector {
|
||||
public Payload listen(KeyPair localKeyPair) {
|
||||
LOG.info("Starting BQP listeners");
|
||||
// Derive commitment
|
||||
byte[] commitment = crypto.deriveKeyCommitment(
|
||||
localKeyPair.getPublic().getEncoded());
|
||||
byte[] commitment = keyAgreementCrypto.deriveKeyCommitment(
|
||||
localKeyPair.getPublic());
|
||||
// Start all listeners and collect their descriptors
|
||||
List<TransportDescriptor> descriptors = new ArrayList<>();
|
||||
for (DuplexPlugin plugin : pluginManager.getKeyAgreementPlugins()) {
|
||||
|
||||
@@ -1,19 +1,10 @@
|
||||
package org.briarproject.bramble.keyagreement;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.data.BdfReaderFactory;
|
||||
import org.briarproject.bramble.api.data.BdfWriterFactory;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementTaskFactory;
|
||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementTask;
|
||||
import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
|
||||
import org.briarproject.bramble.api.keyagreement.PayloadParser;
|
||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.bramble.api.plugin.PluginManager;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
@@ -22,13 +13,9 @@ import dagger.Provides;
|
||||
public class KeyAgreementModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
KeyAgreementTaskFactory provideKeyAgreementTaskFactory(Clock clock,
|
||||
CryptoComponent crypto, EventBus eventBus,
|
||||
@IoExecutor Executor ioExecutor, PayloadEncoder payloadEncoder,
|
||||
PluginManager pluginManager) {
|
||||
return new KeyAgreementTaskFactoryImpl(clock, crypto, eventBus,
|
||||
ioExecutor, payloadEncoder, pluginManager);
|
||||
KeyAgreementTask provideKeyAgreementTask(
|
||||
KeyAgreementTaskImpl keyAgreementTask) {
|
||||
return keyAgreementTask;
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package org.briarproject.bramble.keyagreement;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.KeyAgreementCrypto;
|
||||
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||
import org.briarproject.bramble.api.crypto.KeyParser;
|
||||
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.keyagreement.Payload;
|
||||
import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
|
||||
@@ -11,6 +14,9 @@ import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.MASTER_SECRET_LABEL;
|
||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.SHARED_SECRET_LABEL;
|
||||
|
||||
/**
|
||||
* Implementation of the BQP protocol.
|
||||
* <p/>
|
||||
@@ -57,6 +63,7 @@ class KeyAgreementProtocol {
|
||||
|
||||
private final Callbacks callbacks;
|
||||
private final CryptoComponent crypto;
|
||||
private final KeyAgreementCrypto keyAgreementCrypto;
|
||||
private final PayloadEncoder payloadEncoder;
|
||||
private final KeyAgreementTransport transport;
|
||||
private final Payload theirPayload, ourPayload;
|
||||
@@ -64,11 +71,13 @@ class KeyAgreementProtocol {
|
||||
private final boolean alice;
|
||||
|
||||
KeyAgreementProtocol(Callbacks callbacks, CryptoComponent crypto,
|
||||
KeyAgreementCrypto keyAgreementCrypto,
|
||||
PayloadEncoder payloadEncoder, KeyAgreementTransport transport,
|
||||
Payload theirPayload, Payload ourPayload, KeyPair ourKeyPair,
|
||||
boolean alice) {
|
||||
this.callbacks = callbacks;
|
||||
this.crypto = crypto;
|
||||
this.keyAgreementCrypto = keyAgreementCrypto;
|
||||
this.payloadEncoder = payloadEncoder;
|
||||
this.transport = transport;
|
||||
this.theirPayload = theirPayload;
|
||||
@@ -86,7 +95,7 @@ class KeyAgreementProtocol {
|
||||
*/
|
||||
SecretKey perform() throws AbortException, IOException {
|
||||
try {
|
||||
byte[] theirPublicKey;
|
||||
PublicKey theirPublicKey;
|
||||
if (alice) {
|
||||
sendKey();
|
||||
// Alice waits here until Bob obtains her payload.
|
||||
@@ -104,7 +113,7 @@ class KeyAgreementProtocol {
|
||||
receiveConfirm(s, theirPublicKey);
|
||||
sendConfirm(s, theirPublicKey);
|
||||
}
|
||||
return crypto.deriveMasterSecret(s);
|
||||
return crypto.deriveKey(MASTER_SECRET_LABEL, s);
|
||||
} catch (AbortException e) {
|
||||
sendAbort(e.getCause() != null);
|
||||
throw e;
|
||||
@@ -115,27 +124,34 @@ class KeyAgreementProtocol {
|
||||
transport.sendKey(ourKeyPair.getPublic().getEncoded());
|
||||
}
|
||||
|
||||
private byte[] receiveKey() throws AbortException {
|
||||
byte[] publicKey = transport.receiveKey();
|
||||
private PublicKey receiveKey() throws AbortException {
|
||||
byte[] publicKeyBytes = transport.receiveKey();
|
||||
callbacks.initialRecordReceived();
|
||||
byte[] expected = crypto.deriveKeyCommitment(publicKey);
|
||||
if (!Arrays.equals(expected, theirPayload.getCommitment()))
|
||||
KeyParser keyParser = crypto.getAgreementKeyParser();
|
||||
try {
|
||||
PublicKey publicKey = keyParser.parsePublicKey(publicKeyBytes);
|
||||
byte[] expected = keyAgreementCrypto.deriveKeyCommitment(publicKey);
|
||||
if (!Arrays.equals(expected, theirPayload.getCommitment()))
|
||||
throw new AbortException();
|
||||
return publicKey;
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new AbortException();
|
||||
return publicKey;
|
||||
}
|
||||
}
|
||||
|
||||
private SecretKey deriveSharedSecret(byte[] theirPublicKey)
|
||||
private SecretKey deriveSharedSecret(PublicKey theirPublicKey)
|
||||
throws AbortException {
|
||||
try {
|
||||
return crypto.deriveSharedSecret(theirPublicKey, ourKeyPair, alice);
|
||||
return crypto.deriveSharedSecret(SHARED_SECRET_LABEL,
|
||||
theirPublicKey, ourKeyPair, alice);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new AbortException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendConfirm(SecretKey s, byte[] theirPublicKey)
|
||||
private void sendConfirm(SecretKey s, PublicKey theirPublicKey)
|
||||
throws IOException {
|
||||
byte[] confirm = crypto.deriveConfirmationRecord(s,
|
||||
byte[] confirm = keyAgreementCrypto.deriveConfirmationRecord(s,
|
||||
payloadEncoder.encode(theirPayload),
|
||||
payloadEncoder.encode(ourPayload),
|
||||
theirPublicKey, ourKeyPair,
|
||||
@@ -143,10 +159,10 @@ class KeyAgreementProtocol {
|
||||
transport.sendConfirm(confirm);
|
||||
}
|
||||
|
||||
private void receiveConfirm(SecretKey s, byte[] theirPublicKey)
|
||||
private void receiveConfirm(SecretKey s, PublicKey theirPublicKey)
|
||||
throws AbortException {
|
||||
byte[] confirm = transport.receiveConfirm();
|
||||
byte[] expected = crypto.deriveConfirmationRecord(s,
|
||||
byte[] expected = keyAgreementCrypto.deriveConfirmationRecord(s,
|
||||
payloadEncoder.encode(theirPayload),
|
||||
payloadEncoder.encode(ourPayload),
|
||||
theirPublicKey, ourKeyPair,
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
package org.briarproject.bramble.keyagreement;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementTask;
|
||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementTaskFactory;
|
||||
import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
|
||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.PluginManager;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
class KeyAgreementTaskFactoryImpl implements KeyAgreementTaskFactory {
|
||||
|
||||
private final Clock clock;
|
||||
private final CryptoComponent crypto;
|
||||
private final EventBus eventBus;
|
||||
private final Executor ioExecutor;
|
||||
private final PayloadEncoder payloadEncoder;
|
||||
private final PluginManager pluginManager;
|
||||
|
||||
@Inject
|
||||
KeyAgreementTaskFactoryImpl(Clock clock, CryptoComponent crypto,
|
||||
EventBus eventBus, @IoExecutor Executor ioExecutor,
|
||||
PayloadEncoder payloadEncoder, PluginManager pluginManager) {
|
||||
this.clock = clock;
|
||||
this.crypto = crypto;
|
||||
this.eventBus = eventBus;
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.payloadEncoder = payloadEncoder;
|
||||
this.pluginManager = pluginManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyAgreementTask createTask() {
|
||||
return new KeyAgreementTaskImpl(clock, crypto, eventBus, payloadEncoder,
|
||||
pluginManager, ioExecutor);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.bramble.keyagreement;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.KeyAgreementCrypto;
|
||||
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
@@ -14,6 +15,7 @@ import org.briarproject.bramble.api.keyagreement.event.KeyAgreementFinishedEvent
|
||||
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementListeningEvent;
|
||||
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementStartedEvent;
|
||||
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementWaitingEvent;
|
||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.PluginManager;
|
||||
@@ -23,6 +25,8 @@ import java.io.IOException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@@ -35,6 +39,7 @@ class KeyAgreementTaskImpl extends Thread implements
|
||||
Logger.getLogger(KeyAgreementTaskImpl.class.getName());
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
private final KeyAgreementCrypto keyAgreementCrypto;
|
||||
private final EventBus eventBus;
|
||||
private final PayloadEncoder payloadEncoder;
|
||||
private final KeyPair localKeyPair;
|
||||
@@ -43,14 +48,17 @@ class KeyAgreementTaskImpl extends Thread implements
|
||||
private Payload localPayload;
|
||||
private Payload remotePayload;
|
||||
|
||||
@Inject
|
||||
KeyAgreementTaskImpl(Clock clock, CryptoComponent crypto,
|
||||
EventBus eventBus, PayloadEncoder payloadEncoder,
|
||||
PluginManager pluginManager, Executor ioExecutor) {
|
||||
KeyAgreementCrypto keyAgreementCrypto, EventBus eventBus,
|
||||
PayloadEncoder payloadEncoder, PluginManager pluginManager,
|
||||
@IoExecutor Executor ioExecutor) {
|
||||
this.crypto = crypto;
|
||||
this.keyAgreementCrypto = keyAgreementCrypto;
|
||||
this.eventBus = eventBus;
|
||||
this.payloadEncoder = payloadEncoder;
|
||||
localKeyPair = crypto.generateAgreementKeyPair();
|
||||
connector = new KeyAgreementConnector(this, clock, crypto,
|
||||
connector = new KeyAgreementConnector(this, clock, keyAgreementCrypto,
|
||||
pluginManager, ioExecutor);
|
||||
}
|
||||
|
||||
@@ -100,8 +108,8 @@ class KeyAgreementTaskImpl extends Thread implements
|
||||
// Run BQP protocol over the connection
|
||||
LOG.info("Starting BQP protocol");
|
||||
KeyAgreementProtocol protocol = new KeyAgreementProtocol(this, crypto,
|
||||
payloadEncoder, transport, remotePayload, localPayload,
|
||||
localKeyPair, alice);
|
||||
keyAgreementCrypto, payloadEncoder, transport, remotePayload,
|
||||
localPayload, localKeyPair, alice);
|
||||
try {
|
||||
SecretKey master = protocol.perform();
|
||||
KeyAgreementResult result =
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package org.briarproject.bramble.transport;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.TransportCrypto;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
@@ -20,17 +20,18 @@ class TransportKeyManagerFactoryImpl implements
|
||||
TransportKeyManagerFactory {
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final CryptoComponent crypto;
|
||||
private final TransportCrypto transportCrypto;
|
||||
private final Executor dbExecutor;
|
||||
private final ScheduledExecutorService scheduler;
|
||||
private final Clock clock;
|
||||
|
||||
@Inject
|
||||
TransportKeyManagerFactoryImpl(DatabaseComponent db, CryptoComponent crypto,
|
||||
TransportKeyManagerFactoryImpl(DatabaseComponent db,
|
||||
TransportCrypto transportCrypto,
|
||||
@DatabaseExecutor Executor dbExecutor,
|
||||
@Scheduler ScheduledExecutorService scheduler, Clock clock) {
|
||||
this.db = db;
|
||||
this.crypto = crypto;
|
||||
this.transportCrypto = transportCrypto;
|
||||
this.dbExecutor = dbExecutor;
|
||||
this.scheduler = scheduler;
|
||||
this.clock = clock;
|
||||
@@ -39,8 +40,8 @@ class TransportKeyManagerFactoryImpl implements
|
||||
@Override
|
||||
public TransportKeyManager createTransportKeyManager(
|
||||
TransportId transportId, long maxLatency) {
|
||||
return new TransportKeyManagerImpl(db, crypto, dbExecutor, scheduler,
|
||||
clock, transportId, maxLatency);
|
||||
return new TransportKeyManagerImpl(db, transportCrypto, dbExecutor,
|
||||
scheduler, clock, transportId, maxLatency);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package org.briarproject.bramble.transport;
|
||||
|
||||
import org.briarproject.bramble.api.Bytes;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.crypto.TransportCrypto;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
@@ -41,7 +41,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
Logger.getLogger(TransportKeyManagerImpl.class.getName());
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final CryptoComponent crypto;
|
||||
private final TransportCrypto transportCrypto;
|
||||
private final Executor dbExecutor;
|
||||
private final ScheduledExecutorService scheduler;
|
||||
private final Clock clock;
|
||||
@@ -54,11 +54,12 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
private final Map<ContactId, MutableOutgoingKeys> outContexts;
|
||||
private final Map<ContactId, MutableTransportKeys> keys;
|
||||
|
||||
TransportKeyManagerImpl(DatabaseComponent db, CryptoComponent crypto,
|
||||
Executor dbExecutor, @Scheduler ScheduledExecutorService scheduler,
|
||||
Clock clock, TransportId transportId, long maxLatency) {
|
||||
TransportKeyManagerImpl(DatabaseComponent db,
|
||||
TransportCrypto transportCrypto, Executor dbExecutor,
|
||||
@Scheduler ScheduledExecutorService scheduler, Clock clock,
|
||||
TransportId transportId, long maxLatency) {
|
||||
this.db = db;
|
||||
this.crypto = crypto;
|
||||
this.transportCrypto = transportCrypto;
|
||||
this.dbExecutor = dbExecutor;
|
||||
this.scheduler = scheduler;
|
||||
this.clock = clock;
|
||||
@@ -99,7 +100,8 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
for (Entry<ContactId, TransportKeys> e : keys.entrySet()) {
|
||||
ContactId c = e.getKey();
|
||||
TransportKeys k = e.getValue();
|
||||
TransportKeys k1 = crypto.rotateTransportKeys(k, rotationPeriod);
|
||||
TransportKeys k1 =
|
||||
transportCrypto.rotateTransportKeys(k, rotationPeriod);
|
||||
if (k1.getRotationPeriod() > k.getRotationPeriod())
|
||||
rotationResult.rotated.put(c, k1);
|
||||
rotationResult.current.put(c, k1);
|
||||
@@ -127,7 +129,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
for (long streamNumber : inKeys.getWindow().getUnseen()) {
|
||||
TagContext tagCtx = new TagContext(c, inKeys, streamNumber);
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
crypto.encodeTag(tag, inKeys.getTagKey(), PROTOCOL_VERSION,
|
||||
transportCrypto.encodeTag(tag, inKeys.getTagKey(), PROTOCOL_VERSION,
|
||||
streamNumber);
|
||||
inContexts.put(new Bytes(tag), tagCtx);
|
||||
}
|
||||
@@ -162,11 +164,11 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
// Work out what rotation period the timestamp belongs to
|
||||
long rotationPeriod = timestamp / rotationPeriodLength;
|
||||
// Derive the transport keys
|
||||
TransportKeys k = crypto.deriveTransportKeys(transportId, master,
|
||||
rotationPeriod, alice);
|
||||
TransportKeys k = transportCrypto.deriveTransportKeys(transportId,
|
||||
master, rotationPeriod, alice);
|
||||
// Rotate the keys to the current rotation period if necessary
|
||||
rotationPeriod = clock.currentTimeMillis() / rotationPeriodLength;
|
||||
k = crypto.rotateTransportKeys(k, rotationPeriod);
|
||||
k = transportCrypto.rotateTransportKeys(k, rotationPeriod);
|
||||
// Initialise mutable state for the contact
|
||||
addKeys(c, new MutableTransportKeys(k));
|
||||
// Write the keys back to the DB
|
||||
@@ -234,8 +236,8 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
// Add tags for any stream numbers added to the window
|
||||
for (long streamNumber : change.getAdded()) {
|
||||
byte[] addTag = new byte[TAG_LENGTH];
|
||||
crypto.encodeTag(addTag, inKeys.getTagKey(), PROTOCOL_VERSION,
|
||||
streamNumber);
|
||||
transportCrypto.encodeTag(addTag, inKeys.getTagKey(),
|
||||
PROTOCOL_VERSION, streamNumber);
|
||||
inContexts.put(new Bytes(addTag), new TagContext(
|
||||
tagCtx.contactId, inKeys, streamNumber));
|
||||
}
|
||||
@@ -243,7 +245,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
for (long streamNumber : change.getRemoved()) {
|
||||
if (streamNumber == tagCtx.streamNumber) continue;
|
||||
byte[] removeTag = new byte[TAG_LENGTH];
|
||||
crypto.encodeTag(removeTag, inKeys.getTagKey(),
|
||||
transportCrypto.encodeTag(removeTag, inKeys.getTagKey(),
|
||||
PROTOCOL_VERSION, streamNumber);
|
||||
inContexts.remove(new Bytes(removeTag));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user