diff --git a/briar-core/src/org/briarproject/crypto/EllipticCurveConstants.java b/briar-core/src/org/briarproject/crypto/EllipticCurveConstants.java
index 97e94aed3..b244e1946 100644
--- a/briar-core/src/org/briarproject/crypto/EllipticCurveConstants.java
+++ b/briar-core/src/org/briarproject/crypto/EllipticCurveConstants.java
@@ -5,6 +5,7 @@ import java.math.BigInteger;
import org.spongycastle.crypto.params.ECDomainParameters;
import org.spongycastle.math.ec.ECCurve;
import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.ec.MontgomeryLadderMultiplier;
/** Parameters for curve brainpoolP384r1 - see RFC 5639. */
interface EllipticCurveConstants {
@@ -61,7 +62,8 @@ interface EllipticCurveConstants {
BigInteger H = BigInteger.ONE;
// Static parameter objects derived from the above parameters
- ECCurve CURVE = new ECCurve.Fp(P, A, B);
+ ECCurve CURVE = new ECCurve.Fp(P, A, B).configure().setMultiplier(
+ new MontgomeryLadderMultiplier()).create();
ECPoint G = CURVE.createPoint(X, Y);
ECDomainParameters PARAMETERS = new ECDomainParameters(CURVE, G, Q, H);
}
diff --git a/briar-tests/build.xml b/briar-tests/build.xml
index bcb0b82b0..2d483431d 100644
--- a/briar-tests/build.xml
+++ b/briar-tests/build.xml
@@ -93,6 +93,7 @@
+
diff --git a/briar-tests/src/org/briarproject/crypto/EllipticCurveMultiplicationTest.java b/briar-tests/src/org/briarproject/crypto/EllipticCurveMultiplicationTest.java
new file mode 100644
index 000000000..a2952197e
--- /dev/null
+++ b/briar-tests/src/org/briarproject/crypto/EllipticCurveMultiplicationTest.java
@@ -0,0 +1,111 @@
+package org.briarproject.crypto;
+
+import static org.briarproject.crypto.EllipticCurveConstants.A;
+import static org.briarproject.crypto.EllipticCurveConstants.B;
+import static org.briarproject.crypto.EllipticCurveConstants.CURVE;
+import static org.briarproject.crypto.EllipticCurveConstants.G;
+import static org.briarproject.crypto.EllipticCurveConstants.H;
+import static org.briarproject.crypto.EllipticCurveConstants.P;
+import static org.briarproject.crypto.EllipticCurveConstants.PARAMETERS;
+import static org.briarproject.crypto.EllipticCurveConstants.Q;
+import static org.briarproject.crypto.EllipticCurveConstants.X;
+import static org.briarproject.crypto.EllipticCurveConstants.Y;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.briarproject.BriarTestCase;
+import org.junit.Test;
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
+import org.spongycastle.crypto.generators.ECKeyPairGenerator;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECKeyGenerationParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPoint;
+
+public class EllipticCurveMultiplicationTest extends BriarTestCase {
+
+ @Test
+ public void testMultiplierProducesSameResultsAsDefault() throws Exception {
+ // Construct a curve and base point using the default multiplier
+ ECCurve defaultCurve = new ECCurve.Fp(P, A, B);
+ ECPoint defaultG = defaultCurve.createPoint(X, Y);
+ // Check that the curve and base point are equal to those constructed
+ // using the Montgomery ladder multiplier
+ assertEquals(CURVE, defaultCurve);
+ assertEquals(G, defaultG);
+ // ECDomainParameters doesn't have an equals() method, but it's just a
+ // container for the parameters
+ ECDomainParameters defaultParameters =
+ new ECDomainParameters(defaultCurve, defaultG, Q, H);
+ // Generate two key pairs with each set of parameters, using the same
+ // deterministic PRNG for both sets of parameters
+ byte[] seed = new byte[32];
+ new SecureRandom().nextBytes(seed);
+ // Montgomery ladder multiplier
+ SecureRandom random = new FortunaSecureRandom(seed);
+ ECKeyGenerationParameters montgomeryGeneratorParams =
+ new ECKeyGenerationParameters(PARAMETERS, random);
+ ECKeyPairGenerator montgomeryGenerator = new ECKeyPairGenerator();
+ montgomeryGenerator.init(montgomeryGeneratorParams);
+ AsymmetricCipherKeyPair montgomeryKeyPair1 =
+ montgomeryGenerator.generateKeyPair();
+ ECPrivateKeyParameters montgomeryPrivate1 =
+ (ECPrivateKeyParameters) montgomeryKeyPair1.getPrivate();
+ ECPublicKeyParameters montgomeryPublic1 =
+ (ECPublicKeyParameters) montgomeryKeyPair1.getPublic();
+ AsymmetricCipherKeyPair montgomeryKeyPair2 =
+ montgomeryGenerator.generateKeyPair();
+ ECPrivateKeyParameters montgomeryPrivate2 =
+ (ECPrivateKeyParameters) montgomeryKeyPair2.getPrivate();
+ ECPublicKeyParameters montgomeryPublic2 =
+ (ECPublicKeyParameters) montgomeryKeyPair2.getPublic();
+ // Default multiplier
+ random = new FortunaSecureRandom(seed);
+ ECKeyGenerationParameters defaultGeneratorParams =
+ new ECKeyGenerationParameters(defaultParameters, random);
+ ECKeyPairGenerator defaultGenerator = new ECKeyPairGenerator();
+ defaultGenerator.init(defaultGeneratorParams);
+ AsymmetricCipherKeyPair defaultKeyPair1 =
+ defaultGenerator.generateKeyPair();
+ ECPrivateKeyParameters defaultPrivate1 =
+ (ECPrivateKeyParameters) defaultKeyPair1.getPrivate();
+ ECPublicKeyParameters defaultPublic1 =
+ (ECPublicKeyParameters) defaultKeyPair1.getPublic();
+ AsymmetricCipherKeyPair defaultKeyPair2 =
+ defaultGenerator.generateKeyPair();
+ ECPrivateKeyParameters defaultPrivate2 =
+ (ECPrivateKeyParameters) defaultKeyPair2.getPrivate();
+ ECPublicKeyParameters defaultPublic2 =
+ (ECPublicKeyParameters) defaultKeyPair2.getPublic();
+ // The key pairs generated with both sets of parameters should be equal
+ assertEquals(montgomeryPrivate1.getD(), defaultPrivate1.getD());
+ assertEquals(montgomeryPublic1.getQ(), defaultPublic1.getQ());
+ assertEquals(montgomeryPrivate2.getD(), defaultPrivate2.getD());
+ assertEquals(montgomeryPublic2.getQ(), defaultPublic2.getQ());
+ // OK, all of the above was just sanity checks - now for the test!
+ ECDHCBasicAgreement agreement = new ECDHCBasicAgreement();
+ agreement.init(montgomeryPrivate1);
+ BigInteger sharedSecretMontgomeryMontgomery =
+ agreement.calculateAgreement(montgomeryPublic2);
+ agreement.init(montgomeryPrivate1);
+ BigInteger sharedSecretMontgomeryDefault =
+ agreement.calculateAgreement(defaultPublic2);
+ agreement.init(defaultPrivate1);
+ BigInteger sharedSecretDefaultMontgomery =
+ agreement.calculateAgreement(montgomeryPublic2);
+ agreement.init(defaultPrivate1);
+ BigInteger sharedSecretDefaultDefault =
+ agreement.calculateAgreement(defaultPublic2);
+ // Shared secrets calculated with different multipliers should be equal
+ assertEquals(sharedSecretMontgomeryMontgomery,
+ sharedSecretMontgomeryDefault);
+ assertEquals(sharedSecretMontgomeryMontgomery,
+ sharedSecretDefaultMontgomery);
+ assertEquals(sharedSecretMontgomeryMontgomery,
+ sharedSecretDefaultDefault);
+ }
+}