Skip to content
Snippets Groups Projects
Commit 007ddac8 authored by akwizgran's avatar akwizgran
Browse files

Use the Montgomery ladder multiplier to avoid side-channel attacks.

parent abfff10f
No related branches found
No related tags found
No related merge requests found
......@@ -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);
}
......@@ -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'/>
......
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);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment