mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 06:09:55 +01:00
Use the Montgomery ladder multiplier to avoid side-channel attacks.
This commit is contained in:
@@ -5,6 +5,7 @@ import java.math.BigInteger;
|
|||||||
import org.spongycastle.crypto.params.ECDomainParameters;
|
import org.spongycastle.crypto.params.ECDomainParameters;
|
||||||
import org.spongycastle.math.ec.ECCurve;
|
import org.spongycastle.math.ec.ECCurve;
|
||||||
import org.spongycastle.math.ec.ECPoint;
|
import org.spongycastle.math.ec.ECPoint;
|
||||||
|
import org.spongycastle.math.ec.MontgomeryLadderMultiplier;
|
||||||
|
|
||||||
/** Parameters for curve brainpoolP384r1 - see RFC 5639. */
|
/** Parameters for curve brainpoolP384r1 - see RFC 5639. */
|
||||||
interface EllipticCurveConstants {
|
interface EllipticCurveConstants {
|
||||||
@@ -61,7 +62,8 @@ interface EllipticCurveConstants {
|
|||||||
BigInteger H = BigInteger.ONE;
|
BigInteger H = BigInteger.ONE;
|
||||||
|
|
||||||
// Static parameter objects derived from the above parameters
|
// 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);
|
ECPoint G = CURVE.createPoint(X, Y);
|
||||||
ECDomainParameters PARAMETERS = new ECDomainParameters(CURVE, G, Q, H);
|
ECDomainParameters PARAMETERS = new ECDomainParameters(CURVE, G, Q, H);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,6 +93,7 @@
|
|||||||
<sysproperty key='java.library.path' value='../briar-desktop/libs'/>
|
<sysproperty key='java.library.path' value='../briar-desktop/libs'/>
|
||||||
<test name='org.briarproject.LockFairnessTest'/>
|
<test name='org.briarproject.LockFairnessTest'/>
|
||||||
<test name='org.briarproject.ProtocolIntegrationTest'/>
|
<test name='org.briarproject.ProtocolIntegrationTest'/>
|
||||||
|
<test name='org.briarproject.crypto.EllipticCurveMultiplicationTest'/>
|
||||||
<test name='org.briarproject.crypto.FortunaGeneratorTest'/>
|
<test name='org.briarproject.crypto.FortunaGeneratorTest'/>
|
||||||
<test name='org.briarproject.crypto.FortunaSecureRandomTest'/>
|
<test name='org.briarproject.crypto.FortunaSecureRandomTest'/>
|
||||||
<test name='org.briarproject.crypto.KeyAgreementTest'/>
|
<test name='org.briarproject.crypto.KeyAgreementTest'/>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user