From 0100d62a20cbf0599f34f1429f7515a4e8121ae3 Mon Sep 17 00:00:00 2001 From: akwizgran <akwizgran@users.sourceforge.net> Date: Thu, 27 Mar 2014 10:31:07 +0000 Subject: [PATCH] Test that our elliptic curve is equal to the named curve; benchmarks. --- .../EllipticCurveMultiplicationTest.java | 28 ++-- .../crypto/EllipticCurvePerformanceTest.java | 139 ++++++++++++++++++ 2 files changed, 155 insertions(+), 12 deletions(-) create mode 100644 briar-tests/src/org/briarproject/crypto/EllipticCurvePerformanceTest.java diff --git a/briar-tests/src/org/briarproject/crypto/EllipticCurveMultiplicationTest.java b/briar-tests/src/org/briarproject/crypto/EllipticCurveMultiplicationTest.java index a2952197e4..12e15dce75 100644 --- a/briar-tests/src/org/briarproject/crypto/EllipticCurveMultiplicationTest.java +++ b/briar-tests/src/org/briarproject/crypto/EllipticCurveMultiplicationTest.java @@ -1,21 +1,18 @@ 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.asn1.teletrust.TeleTrusTNamedCurves; +import org.spongycastle.asn1.x9.X9ECParameters; import org.spongycastle.crypto.AsymmetricCipherKeyPair; import org.spongycastle.crypto.agreement.ECDHCBasicAgreement; import org.spongycastle.crypto.generators.ECKeyPairGenerator; @@ -30,17 +27,24 @@ 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 + // Instantiate the built-in implementation of the curve, which uses + // the default multiplier + X9ECParameters defaultX9Parameters = + TeleTrusTNamedCurves.getByName("brainpoolp384r1"); + ECCurve defaultCurve = defaultX9Parameters.getCurve(); + ECPoint defaultG = defaultX9Parameters.getG(); + BigInteger defaultQ = defaultX9Parameters.getN(); + BigInteger defaultH = defaultX9Parameters.getH(); + // Check that the built-in parameters are equal to our parameters, + // which use the Montgomery ladder multiplier assertEquals(CURVE, defaultCurve); assertEquals(G, defaultG); + assertEquals(Q, defaultQ); + assertEquals(H, defaultH); // ECDomainParameters doesn't have an equals() method, but it's just a // container for the parameters - ECDomainParameters defaultParameters = - new ECDomainParameters(defaultCurve, defaultG, Q, H); + ECDomainParameters defaultParameters = new ECDomainParameters( + defaultCurve, defaultG, defaultQ, defaultH); // Generate two key pairs with each set of parameters, using the same // deterministic PRNG for both sets of parameters byte[] seed = new byte[32]; diff --git a/briar-tests/src/org/briarproject/crypto/EllipticCurvePerformanceTest.java b/briar-tests/src/org/briarproject/crypto/EllipticCurvePerformanceTest.java new file mode 100644 index 0000000000..fdc0e04b2f --- /dev/null +++ b/briar-tests/src/org/briarproject/crypto/EllipticCurvePerformanceTest.java @@ -0,0 +1,139 @@ +package org.briarproject.crypto; + +import java.math.BigInteger; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.spongycastle.asn1.sec.SECNamedCurves; +import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves; +import org.spongycastle.asn1.x9.X9ECParameters; +import org.spongycastle.crypto.AsymmetricCipherKeyPair; +import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.agreement.ECDHCBasicAgreement; +import org.spongycastle.crypto.digests.SHA384Digest; +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.crypto.params.ParametersWithRandom; +import org.spongycastle.crypto.signers.DSADigestSigner; +import org.spongycastle.crypto.signers.DSAKCalculator; +import org.spongycastle.crypto.signers.ECDSASigner; +import org.spongycastle.crypto.signers.HMacDSAKCalculator; +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.ec.MontgomeryLadderMultiplier; + +// Not a JUnit test +public class EllipticCurvePerformanceTest { + + private static final SecureRandom random = new SecureRandom(); + private static final int SAMPLES = 50; + private static final int BYTES_TO_SIGN = 1024; + private static final List<String> SEC_NAMES = Arrays.asList( + "secp256k1", "secp256r1", "secp384r1", "secp521r1"); + private static final List<String> BRAINPOOL_NAMES = Arrays.asList( + "brainpoolp256r1", "brainpoolp384r1", "brainpoolp512r1"); + + public static void main(String[] args) { + for(String name : SEC_NAMES) { + ECDomainParameters params = + convertParams(SECNamedCurves.getByName(name)); + runTest(name + " default", params); + runTest(name + " constant", constantTime(params)); + } + for(String name : BRAINPOOL_NAMES) { + ECDomainParameters params = + convertParams(TeleTrusTNamedCurves.getByName(name)); + runTest(name + " default", params); + runTest(name + " constant", constantTime(params)); + } + runTest("ours", EllipticCurveConstants.PARAMETERS); + } + + private static void runTest(String name, ECDomainParameters params) { + // Generate two key pairs using the given parameters + ECKeyGenerationParameters generatorParams = + new ECKeyGenerationParameters(params, random); + ECKeyPairGenerator generator = new ECKeyPairGenerator(); + generator.init(generatorParams); + AsymmetricCipherKeyPair keyPair1 = generator.generateKeyPair(); + ECPublicKeyParameters public1 = + (ECPublicKeyParameters) keyPair1.getPublic(); + ECPrivateKeyParameters private1 = + (ECPrivateKeyParameters) keyPair1.getPrivate(); + AsymmetricCipherKeyPair keyPair2 = generator.generateKeyPair(); + ECPublicKeyParameters public2 = + (ECPublicKeyParameters) keyPair2.getPublic(); + // Time some ECDH key agreements + List<Long> samples = new ArrayList<Long>(); + for(int i = 0; i < SAMPLES; i++) { + ECDHCBasicAgreement agreement = new ECDHCBasicAgreement(); + long start = System.nanoTime(); + agreement.init(private1); + agreement.calculateAgreement(public2); + samples.add(System.nanoTime() - start); + } + long agreementMedian = median(samples); + // Time some signatures + List<byte[]> signatures = new ArrayList<byte[]>(); + samples.clear(); + for(int i = 0; i < SAMPLES; i++) { + Digest digest = new SHA384Digest(); + DSAKCalculator calculator = new HMacDSAKCalculator(digest); + DSADigestSigner signer = new DSADigestSigner(new ECDSASigner( + calculator), digest); + long start = System.nanoTime(); + signer.init(true, new ParametersWithRandom(private1, random)); + signer.update(new byte[BYTES_TO_SIGN], 0, BYTES_TO_SIGN); + signatures.add(signer.generateSignature()); + samples.add(System.nanoTime() - start); + } + long signatureMedian = median(samples); + // Time some signature verifications + samples.clear(); + for(int i = 0; i < SAMPLES; i++) { + Digest digest = new SHA384Digest(); + DSAKCalculator calculator = new HMacDSAKCalculator(digest); + DSADigestSigner signer = new DSADigestSigner(new ECDSASigner( + calculator), digest); + long start = System.nanoTime(); + signer.init(false, public1); + signer.update(new byte[BYTES_TO_SIGN], 0, BYTES_TO_SIGN); + if(!signer.verifySignature(signatures.get(i))) + throw new AssertionError(); + samples.add(System.nanoTime() - start); + } + long verificationMedian = median(samples); + System.out.println(name + ": " + + agreementMedian + " " + + signatureMedian + " " + + verificationMedian); + } + + private static long median(List<Long> list) { + int size = list.size(); + if(size == 0) throw new IllegalArgumentException(); + Collections.sort(list); + if(size % 2 == 1) return list.get(size / 2); + return list.get(size / 2 - 1) + list.get(size / 2) / 2; + } + + private static ECDomainParameters convertParams(X9ECParameters in) { + return new ECDomainParameters(in.getCurve(), in.getG(), in.getN(), + in.getH()); + } + + private static ECDomainParameters constantTime(ECDomainParameters in) { + ECCurve curve = in.getCurve().configure().setMultiplier( + new MontgomeryLadderMultiplier()).create(); + BigInteger x = in.getG().getAffineXCoord().toBigInteger(); + BigInteger y = in.getG().getAffineYCoord().toBigInteger(); + ECPoint g = curve.createPoint(x, y); + return new ECDomainParameters(curve, g, in.getN(), in.getH()); + } +} -- GitLab