From 007ddac88048815b2e80b15b0bda110ef7908378 Mon Sep 17 00:00:00 2001 From: akwizgran <akwizgran@users.sourceforge.net> Date: Wed, 19 Mar 2014 22:52:53 +0000 Subject: [PATCH] Use the Montgomery ladder multiplier to avoid side-channel attacks. --- .../crypto/EllipticCurveConstants.java | 4 +- briar-tests/build.xml | 1 + .../EllipticCurveMultiplicationTest.java | 111 ++++++++++++++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 briar-tests/src/org/briarproject/crypto/EllipticCurveMultiplicationTest.java diff --git a/briar-core/src/org/briarproject/crypto/EllipticCurveConstants.java b/briar-core/src/org/briarproject/crypto/EllipticCurveConstants.java index 97e94aed3f..b244e19467 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 bcb0b82b00..2d483431d3 100644 --- a/briar-tests/build.xml +++ b/briar-tests/build.xml @@ -93,6 +93,7 @@ <sysproperty key='java.library.path' value='../briar-desktop/libs'/> <test name='org.briarproject.LockFairnessTest'/> <test name='org.briarproject.ProtocolIntegrationTest'/> + <test name='org.briarproject.crypto.EllipticCurveMultiplicationTest'/> <test name='org.briarproject.crypto.FortunaGeneratorTest'/> <test name='org.briarproject.crypto.FortunaSecureRandomTest'/> <test name='org.briarproject.crypto.KeyAgreementTest'/> 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 0000000000..a2952197e4 --- /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); + } +} -- GitLab