mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 20:59:54 +01:00
Use Curve25519 for key agreement.
This commit is contained in:
@@ -14,15 +14,11 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.system.SecureRandomProvider;
|
||||
import org.briarproject.bramble.util.ByteUtils;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
|
||||
import org.spongycastle.crypto.CryptoException;
|
||||
import org.spongycastle.crypto.Digest;
|
||||
import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
|
||||
import org.spongycastle.crypto.digests.Blake2bDigest;
|
||||
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
|
||||
import org.spongycastle.crypto.params.ECKeyGenerationParameters;
|
||||
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.spongycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.whispersystems.curve25519.Curve25519;
|
||||
import org.whispersystems.curve25519.Curve25519KeyPair;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@@ -35,7 +31,6 @@ import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static org.briarproject.bramble.crypto.EllipticCurveConstants.PARAMETERS;
|
||||
import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
|
||||
|
||||
@NotNullByDefault
|
||||
@@ -44,7 +39,6 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(CryptoComponentImpl.class.getName());
|
||||
|
||||
private static final int AGREEMENT_KEY_PAIR_BITS = 256;
|
||||
private static final int SIGNATURE_KEY_PAIR_BITS = 256;
|
||||
private static final int STORAGE_IV_BYTES = 24; // 196 bits
|
||||
private static final int PBKDF_SALT_BYTES = 32; // 256 bits
|
||||
@@ -52,7 +46,7 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
|
||||
private final SecureRandom secureRandom;
|
||||
private final PasswordBasedKdf passwordBasedKdf;
|
||||
private final ECKeyPairGenerator agreementKeyPairGenerator;
|
||||
private final Curve25519 curve25519;
|
||||
private final KeyPairGenerator signatureKeyPairGenerator;
|
||||
private final KeyParser agreementKeyParser, signatureKeyParser;
|
||||
private final MessageEncrypter messageEncrypter;
|
||||
@@ -80,15 +74,11 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
}
|
||||
secureRandom = new SecureRandom();
|
||||
this.passwordBasedKdf = passwordBasedKdf;
|
||||
ECKeyGenerationParameters params = new ECKeyGenerationParameters(
|
||||
PARAMETERS, secureRandom);
|
||||
agreementKeyPairGenerator = new ECKeyPairGenerator();
|
||||
agreementKeyPairGenerator.init(params);
|
||||
curve25519 = Curve25519.getInstance("java");
|
||||
signatureKeyPairGenerator = new KeyPairGenerator();
|
||||
signatureKeyPairGenerator.initialize(SIGNATURE_KEY_PAIR_BITS,
|
||||
secureRandom);
|
||||
agreementKeyParser = new Sec1KeyParser(PARAMETERS,
|
||||
AGREEMENT_KEY_PAIR_BITS);
|
||||
agreementKeyParser = new Curve25519KeyParser();
|
||||
signatureKeyParser = new EdKeyParser();
|
||||
messageEncrypter = new MessageEncrypter(secureRandom);
|
||||
}
|
||||
@@ -133,16 +123,17 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
// Package access for testing
|
||||
byte[] performRawKeyAgreement(PrivateKey priv, PublicKey pub)
|
||||
throws GeneralSecurityException {
|
||||
if (!(priv instanceof Sec1PrivateKey))
|
||||
if (!(priv instanceof Curve25519PrivateKey))
|
||||
throw new IllegalArgumentException();
|
||||
if (!(pub instanceof Sec1PublicKey))
|
||||
if (!(pub instanceof Curve25519PublicKey))
|
||||
throw new IllegalArgumentException();
|
||||
ECPrivateKeyParameters ecPriv = ((Sec1PrivateKey) priv).getKey();
|
||||
ECPublicKeyParameters ecPub = ((Sec1PublicKey) pub).getKey();
|
||||
long now = System.currentTimeMillis();
|
||||
ECDHCBasicAgreement agreement = new ECDHCBasicAgreement();
|
||||
agreement.init(ecPriv);
|
||||
byte[] secret = agreement.calculateAgreement(ecPub).toByteArray();
|
||||
byte[] secret = curve25519.calculateAgreement(pub.getEncoded(),
|
||||
priv.getEncoded());
|
||||
// If the shared secret is all zeroes, the public key is invalid
|
||||
byte allZero = 0;
|
||||
for (byte b : secret) allZero |= b;
|
||||
if (allZero == 0) throw new GeneralSecurityException();
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Deriving shared secret took " + duration + " ms");
|
||||
@@ -151,18 +142,10 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
|
||||
@Override
|
||||
public KeyPair generateAgreementKeyPair() {
|
||||
AsymmetricCipherKeyPair keyPair =
|
||||
agreementKeyPairGenerator.generateKeyPair();
|
||||
// Return a wrapper that uses the SEC 1 encoding
|
||||
ECPublicKeyParameters ecPublicKey =
|
||||
(ECPublicKeyParameters) keyPair.getPublic();
|
||||
PublicKey publicKey = new Sec1PublicKey(ecPublicKey
|
||||
);
|
||||
ECPrivateKeyParameters ecPrivateKey =
|
||||
(ECPrivateKeyParameters) keyPair.getPrivate();
|
||||
PrivateKey privateKey = new Sec1PrivateKey(ecPrivateKey,
|
||||
AGREEMENT_KEY_PAIR_BITS);
|
||||
return new KeyPair(publicKey, privateKey);
|
||||
Curve25519KeyPair keyPair = curve25519.generateKeyPair();
|
||||
PublicKey pub = new Curve25519PublicKey(keyPair.getPublicKey());
|
||||
PrivateKey priv = new Curve25519PrivateKey(keyPair.getPrivateKey());
|
||||
return new KeyPair(pub, priv);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -172,7 +155,8 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
|
||||
@Override
|
||||
public KeyPair generateSignatureKeyPair() {
|
||||
java.security.KeyPair keyPair = signatureKeyPairGenerator.generateKeyPair();
|
||||
java.security.KeyPair keyPair =
|
||||
signatureKeyPairGenerator.generateKeyPair();
|
||||
EdDSAPublicKey edPublicKey = (EdDSAPublicKey) keyPair.getPublic();
|
||||
PublicKey publicKey = new EdPublicKey(edPublicKey.getAbyte());
|
||||
EdDSAPrivateKey edPrivateKey = (EdDSAPrivateKey) keyPair.getPrivate();
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.briarproject.bramble.crypto;
|
||||
|
||||
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.nullsafety.NotNullByDefault;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
@NotNullByDefault
|
||||
class Curve25519KeyParser implements KeyParser {
|
||||
|
||||
@Override
|
||||
public PublicKey parsePublicKey(byte[] encodedKey)
|
||||
throws GeneralSecurityException {
|
||||
if (encodedKey.length != 32) throw new GeneralSecurityException();
|
||||
return new Curve25519PublicKey(encodedKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrivateKey parsePrivateKey(byte[] encodedKey)
|
||||
throws GeneralSecurityException {
|
||||
if (encodedKey.length != 32) throw new GeneralSecurityException();
|
||||
return new Curve25519PrivateKey(encodedKey);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.briarproject.bramble.crypto;
|
||||
|
||||
import org.briarproject.bramble.api.Bytes;
|
||||
import org.briarproject.bramble.api.crypto.PrivateKey;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@NotNullByDefault
|
||||
class Curve25519PrivateKey extends Bytes implements PrivateKey {
|
||||
|
||||
Curve25519PrivateKey(byte[] bytes) {
|
||||
super(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
return getBytes();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.briarproject.bramble.crypto;
|
||||
|
||||
import org.briarproject.bramble.api.Bytes;
|
||||
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@NotNullByDefault
|
||||
class Curve25519PublicKey extends Bytes implements PublicKey {
|
||||
|
||||
Curve25519PublicKey(byte[] bytes) {
|
||||
super(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
return getBytes();
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package org.briarproject.bramble.crypto;
|
||||
|
||||
import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
|
||||
import org.spongycastle.asn1.x9.X9ECParameters;
|
||||
import org.spongycastle.crypto.params.ECDomainParameters;
|
||||
import org.spongycastle.math.ec.ECCurve;
|
||||
import org.spongycastle.math.ec.ECMultiplier;
|
||||
import org.spongycastle.math.ec.ECPoint;
|
||||
import org.spongycastle.math.ec.MontgomeryLadderMultiplier;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Parameters for curve brainpoolp256r1 - see RFC 5639.
|
||||
*/
|
||||
class EllipticCurveConstants {
|
||||
|
||||
static final ECDomainParameters PARAMETERS;
|
||||
|
||||
static {
|
||||
// Start with the default implementation of the curve
|
||||
X9ECParameters x9 = TeleTrusTNamedCurves.getByName("brainpoolp256r1");
|
||||
// Use a constant-time multiplier
|
||||
ECMultiplier monty = new MontgomeryLadderMultiplier();
|
||||
ECCurve curve = x9.getCurve().configure().setMultiplier(monty).create();
|
||||
BigInteger gX = x9.getG().getAffineXCoord().toBigInteger();
|
||||
BigInteger gY = x9.getG().getAffineYCoord().toBigInteger();
|
||||
ECPoint g = curve.createPoint(gX, gY);
|
||||
// Convert to ECDomainParameters using the new multiplier
|
||||
PARAMETERS = new ECDomainParameters(curve, g, x9.getN(), x9.getH());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user