From 112d80420c95e590b2425738c1713125381d8251 Mon Sep 17 00:00:00 2001 From: akwizgran <akwizgran@users.sourceforge.net> Date: Fri, 9 Jan 2015 13:23:18 +0000 Subject: [PATCH] Downgrade to 256-bit curve for performance. Also reduced hash function to 256 bits because our target security level is now 128 bits. --- .../org/briarproject/api/AuthorConstants.java | 10 +-- .../src/org/briarproject/api/UniqueId.java | 2 +- .../crypto/CryptoComponentImpl.java | 19 +++-- .../crypto/EllipticCurveConstants.java | 79 +++++-------------- .../briarproject/crypto/Sec1KeyParser.java | 4 +- .../briarproject/crypto/SignatureImpl.java | 4 +- .../src/org/briarproject/db/JdbcDatabase.java | 4 +- .../EllipticCurveMultiplicationTest.java | 24 +++--- .../crypto/EllipticCurvePerformanceTest.java | 6 +- .../briarproject/messaging/ConsumersTest.java | 4 +- 10 files changed, 55 insertions(+), 101 deletions(-) diff --git a/briar-api/src/org/briarproject/api/AuthorConstants.java b/briar-api/src/org/briarproject/api/AuthorConstants.java index 57ad598a75..1b2123d957 100644 --- a/briar-api/src/org/briarproject/api/AuthorConstants.java +++ b/briar-api/src/org/briarproject/api/AuthorConstants.java @@ -11,9 +11,9 @@ public interface AuthorConstants { * Public keys use SEC1 format: 0x04 x y, where x and y are unsigned * big-endian integers. * <p> - * For a 384-bit elliptic curve, the maximum length is 2 * (384/8) + 1. + * For a 256-bit elliptic curve, the maximum length is 2 * 256 / 8 + 1. */ - int MAX_PUBLIC_KEY_LENGTH = 97; + int MAX_PUBLIC_KEY_LENGTH = 65; /** * The maximum length of a signature in bytes. @@ -24,8 +24,8 @@ public interface AuthorConstants { * length, len3 is len(s) as a DER length, and r and s are signed * big-endian integers of minimal length. * <p> - * For a 384-bit elliptic curve, the lengths are one byte each, so the - * maximum length is 2 * (384/8) + 8. + * For a 256-bit elliptic curve, the lengths are one byte each, so the + * maximum length is 2 * 256 / 8 + 8. */ - int MAX_SIGNATURE_LENGTH = 104; + int MAX_SIGNATURE_LENGTH = 72; } diff --git a/briar-api/src/org/briarproject/api/UniqueId.java b/briar-api/src/org/briarproject/api/UniqueId.java index 38d4e9bc48..75cf1f6509 100644 --- a/briar-api/src/org/briarproject/api/UniqueId.java +++ b/briar-api/src/org/briarproject/api/UniqueId.java @@ -5,7 +5,7 @@ import java.util.Arrays; public abstract class UniqueId { /** The length of a unique identifier in bytes. */ - public static final int LENGTH = 48; + public static final int LENGTH = 32; protected final byte[] id; diff --git a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java index 34a36f0fdc..8685f56ac7 100644 --- a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java +++ b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java @@ -3,7 +3,6 @@ package org.briarproject.crypto; import static java.util.logging.Level.INFO; import static org.briarproject.api.invitation.InvitationConstants.CODE_BITS; import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH; -import static org.briarproject.crypto.EllipticCurveConstants.P; import static org.briarproject.crypto.EllipticCurveConstants.PARAMETERS; import static org.briarproject.util.ByteUtils.MAX_32_BIT_UNSIGNED; @@ -35,7 +34,7 @@ import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.Digest; import org.spongycastle.crypto.Mac; import org.spongycastle.crypto.agreement.ECDHCBasicAgreement; -import org.spongycastle.crypto.digests.SHA384Digest; +import org.spongycastle.crypto.digests.SHA256Digest; import org.spongycastle.crypto.engines.AESLightEngine; import org.spongycastle.crypto.generators.ECKeyPairGenerator; import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator; @@ -51,8 +50,8 @@ class CryptoComponentImpl implements CryptoComponent { Logger.getLogger(CryptoComponentImpl.class.getName()); private static final int CIPHER_KEY_BYTES = 32; // 256 bits - private static final int AGREEMENT_KEY_PAIR_BITS = 384; - private static final int SIGNATURE_KEY_PAIR_BITS = 384; + private static final int AGREEMENT_KEY_PAIR_BITS = 256; + private static final int SIGNATURE_KEY_PAIR_BITS = 256; private static final int STORAGE_IV_BYTES = 16; // 128 bits private static final int PBKDF_SALT_BYTES = 16; // 128 bits private static final int PBKDF_TARGET_MILLIS = 500; @@ -99,9 +98,9 @@ class CryptoComponentImpl implements CryptoComponent { agreementKeyPairGenerator.init(params); signatureKeyPairGenerator = new ECKeyPairGenerator(); signatureKeyPairGenerator.init(params); - agreementKeyParser = new Sec1KeyParser(PARAMETERS, P, + agreementKeyParser = new Sec1KeyParser(PARAMETERS, AGREEMENT_KEY_PAIR_BITS); - signatureKeyParser = new Sec1KeyParser(PARAMETERS, P, + signatureKeyParser = new Sec1KeyParser(PARAMETERS, SIGNATURE_KEY_PAIR_BITS); } @@ -112,7 +111,7 @@ class CryptoComponentImpl implements CryptoComponent { } public MessageDigest getMessageDigest() { - return new DoubleDigest(new SHA384Digest()); + return new DoubleDigest(new SHA256Digest()); } public PseudoRandom getPseudoRandom(int seed1, int seed2) { @@ -405,7 +404,7 @@ class CryptoComponentImpl implements CryptoComponent { if(label[label.length - 1] != '\0') throw new IllegalArgumentException(); // Initialise the PRF - Mac prf = new HMac(new SHA384Digest()); + Mac prf = new HMac(new SHA256Digest()); KeyParameter k = new KeyParameter(secret); prf.init(k); int macLength = prf.getMacSize(); @@ -426,7 +425,7 @@ class CryptoComponentImpl implements CryptoComponent { // Password-based key derivation function - see PKCS#5 v2.1, section 5.2 private byte[] pbkdf2(String password, byte[] salt, int iterations) { byte[] utf8 = StringUtils.toUtf8(password); - Digest digest = new SHA384Digest(); + Digest digest = new SHA256Digest(); PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(digest); gen.init(utf8, salt, iterations); int keyLengthInBits = CIPHER_KEY_BYTES * 8; @@ -468,7 +467,7 @@ class CryptoComponentImpl implements CryptoComponent { byte[] salt = new byte[PBKDF_SALT_BYTES]; int keyLengthInBits = CIPHER_KEY_BYTES * 8; long start = System.nanoTime(); - Digest digest = new SHA384Digest(); + Digest digest = new SHA256Digest(); PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(digest); gen.init(password, salt, iterations); gen.generateDerivedParameters(keyLengthInBits); diff --git a/briar-core/src/org/briarproject/crypto/EllipticCurveConstants.java b/briar-core/src/org/briarproject/crypto/EllipticCurveConstants.java index b244e19467..76be537299 100644 --- a/briar-core/src/org/briarproject/crypto/EllipticCurveConstants.java +++ b/briar-core/src/org/briarproject/crypto/EllipticCurveConstants.java @@ -2,68 +2,29 @@ package org.briarproject.crypto; import java.math.BigInteger; +import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves; +import org.spongycastle.asn1.x9.X9ECParameters; import org.spongycastle.crypto.params.ECDomainParameters; import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECMultiplier; import org.spongycastle.math.ec.ECPoint; import org.spongycastle.math.ec.MontgomeryLadderMultiplier; -/** Parameters for curve brainpoolP384r1 - see RFC 5639. */ -interface EllipticCurveConstants { - - /** - * The prime specifying the finite field. (This is called p in RFC 5639 and - * q in SEC 2.) - */ - BigInteger P = new BigInteger("8CB91E82" + "A3386D28" + "0F5D6F7E" + - "50E641DF" + "152F7109" + "ED5456B4" + "12B1DA19" + "7FB71123" + - "ACD3A729" + "901D1A71" + "87470013" + "3107EC53", 16); - - /** - * A coefficient of the equation y^2 = x^3 + A*x + B defining the elliptic - * curve. (This is called A in RFC 5639 and a in SEC 2.) - */ - BigInteger A = new BigInteger("7BC382C6" + "3D8C150C" + "3C72080A" + - "CE05AFA0" + "C2BEA28E" + "4FB22787" + "139165EF" + "BA91F90F" + - "8AA5814A" + "503AD4EB" + "04A8C7DD" + "22CE2826", 16); - - /** - * A coefficient of the equation y^2 = x^3 + A*x + B defining the elliptic - * curve. (This is called B in RFC 5639 b in SEC 2.) - */ - BigInteger B = new BigInteger("04A8C7DD" + "22CE2826" + "8B39B554" + - "16F0447C" + "2FB77DE1" + "07DCD2A6" + "2E880EA5" + "3EEB62D5" + - "7CB43902" + "95DBC994" + "3AB78696" + "FA504C11", 16); - - /** - * The x co-ordinate of the base point G. (This is called x in RFC 5639 and - * SEC 2.) - */ - BigInteger X = new BigInteger("1D1C64F0" + "68CF45FF" + "A2A63A81" + - "B7C13F6B" + "8847A3E7" + "7EF14FE3" + "DB7FCAFE" + "0CBD10E8" + - "E826E034" + "36D646AA" + "EF87B2E2" + "47D4AF1E", 16); - - /** - * The y co-ordinate of the base point G. (This is called y in RFC 5639 and - * SEC 2.) - */ - BigInteger Y = new BigInteger("8ABE1D75" + "20F9C2A4" + "5CB1EB8E" + - "95CFD552" + "62B70B29" + "FEEC5864" + "E19C054F" + "F9912928" + - "0E464621" + "77918111" + "42820341" + "263C5315", 16); - - /** - * The order of the base point G. (This is called q in RFC 5639 and n in - * SEC 2.) - */ - BigInteger Q = new BigInteger("8CB91E82" + "A3386D28" + "0F5D6F7E" + - "50E641DF" + "152F7109" + "ED5456B3" + "1F166E6C" + "AC0425A7" + - "CF3AB6AF" + "6B7FC310" + "3B883202" + "E9046565", 16); - - /** The cofactor of G. (This is called h in RFC 5639 and SEC 2.) */ - BigInteger H = BigInteger.ONE; - - // Static parameter objects derived from the above parameters - 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); +/** Parameters for curve brainpoolp256r1 - see RFC 5639. */ +class EllipticCurveConstants { + + static final ECDomainParameters PARAMETERS; + + static { + // Start with the default implementation of the curve + X9ECParameters x9 = TeleTrusTNamedCurves.getByName("brainpoolp256r1"); + // Use a constant-time multiplier + ECMultiplier monty = new MontgomeryLadderMultiplier(); + ECCurve curve = x9.getCurve().configure().setMultiplier(monty).create(); + BigInteger gX = x9.getG().getAffineXCoord().toBigInteger(); + BigInteger gY = x9.getG().getAffineYCoord().toBigInteger(); + ECPoint g = curve.createPoint(gX, gY); + // Convert to ECDomainParameters using the new multiplier + PARAMETERS = new ECDomainParameters(curve, g, x9.getN(), x9.getH()); + } } diff --git a/briar-core/src/org/briarproject/crypto/Sec1KeyParser.java b/briar-core/src/org/briarproject/crypto/Sec1KeyParser.java index efb3b7781d..d383138d98 100644 --- a/briar-core/src/org/briarproject/crypto/Sec1KeyParser.java +++ b/briar-core/src/org/briarproject/crypto/Sec1KeyParser.java @@ -29,10 +29,10 @@ class Sec1KeyParser implements KeyParser { private final BigInteger modulus; private final int keyBits, bytesPerInt, publicKeyBytes, privateKeyBytes; - Sec1KeyParser(ECDomainParameters params, BigInteger modulus, int keyBits) { + Sec1KeyParser(ECDomainParameters params, int keyBits) { this.params = params; - this.modulus = modulus; this.keyBits = keyBits; + modulus = ((ECCurve.Fp) params.getCurve()).getQ(); bytesPerInt = (keyBits + 7) / 8; publicKeyBytes = 1 + 2 * bytesPerInt; privateKeyBytes = bytesPerInt; diff --git a/briar-core/src/org/briarproject/crypto/SignatureImpl.java b/briar-core/src/org/briarproject/crypto/SignatureImpl.java index a79e8dc63c..0c2a02eb4a 100644 --- a/briar-core/src/org/briarproject/crypto/SignatureImpl.java +++ b/briar-core/src/org/briarproject/crypto/SignatureImpl.java @@ -7,7 +7,7 @@ import org.briarproject.api.crypto.PrivateKey; import org.briarproject.api.crypto.PublicKey; import org.briarproject.api.crypto.Signature; import org.spongycastle.crypto.Digest; -import org.spongycastle.crypto.digests.SHA384Digest; +import org.spongycastle.crypto.digests.SHA256Digest; import org.spongycastle.crypto.params.ECPrivateKeyParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.crypto.params.ParametersWithRandom; @@ -23,7 +23,7 @@ class SignatureImpl implements Signature { SignatureImpl(SecureRandom secureRandom) { this.secureRandom = secureRandom; - Digest digest = new SHA384Digest(); + Digest digest = new SHA256Digest(); DSAKCalculator calculator = new HMacDSAKCalculator(digest); signer = new DSADigestSigner(new ECDSASigner(calculator), digest); } diff --git a/briar-core/src/org/briarproject/db/JdbcDatabase.java b/briar-core/src/org/briarproject/db/JdbcDatabase.java index d131b4a1d2..aaa8aee814 100644 --- a/briar-core/src/org/briarproject/db/JdbcDatabase.java +++ b/briar-core/src/org/briarproject/db/JdbcDatabase.java @@ -62,8 +62,8 @@ import org.briarproject.api.transport.TemporarySecret; */ abstract class JdbcDatabase implements Database<Connection> { - private static final int SCHEMA_VERSION = 7; - private static final int MIN_SCHEMA_VERSION = 7; + private static final int SCHEMA_VERSION = 8; + private static final int MIN_SCHEMA_VERSION = 8; private static final String CREATE_SETTINGS = "CREATE TABLE settings" diff --git a/briar-tests/src/org/briarproject/crypto/EllipticCurveMultiplicationTest.java b/briar-tests/src/org/briarproject/crypto/EllipticCurveMultiplicationTest.java index 12e15dce75..c3f2dd1853 100644 --- a/briar-tests/src/org/briarproject/crypto/EllipticCurveMultiplicationTest.java +++ b/briar-tests/src/org/briarproject/crypto/EllipticCurveMultiplicationTest.java @@ -1,10 +1,6 @@ package org.briarproject.crypto; -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.PARAMETERS; -import static org.briarproject.crypto.EllipticCurveConstants.Q; import java.math.BigInteger; import java.security.SecureRandom; @@ -27,24 +23,22 @@ public class EllipticCurveMultiplicationTest extends BriarTestCase { @Test public void testMultiplierProducesSameResultsAsDefault() throws Exception { - // Instantiate the built-in implementation of the curve, which uses - // the default multiplier + // Instantiate the default implementation of the curve X9ECParameters defaultX9Parameters = - TeleTrusTNamedCurves.getByName("brainpoolp384r1"); + TeleTrusTNamedCurves.getByName("brainpoolp256r1"); ECCurve defaultCurve = defaultX9Parameters.getCurve(); ECPoint defaultG = defaultX9Parameters.getG(); - BigInteger defaultQ = defaultX9Parameters.getN(); + BigInteger defaultN = 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); + // Check that the default parameters are equal to our parameters + assertEquals(PARAMETERS.getCurve(), defaultCurve); + assertEquals(PARAMETERS.getG(), defaultG); + assertEquals(PARAMETERS.getN(), defaultN); + assertEquals(PARAMETERS.getH(), defaultH); // ECDomainParameters doesn't have an equals() method, but it's just a // container for the parameters ECDomainParameters defaultParameters = new ECDomainParameters( - defaultCurve, defaultG, defaultQ, defaultH); + defaultCurve, defaultG, defaultN, 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 index fdc0e04b2f..fd876bc99e 100644 --- a/briar-tests/src/org/briarproject/crypto/EllipticCurvePerformanceTest.java +++ b/briar-tests/src/org/briarproject/crypto/EllipticCurvePerformanceTest.java @@ -13,7 +13,7 @@ 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.digests.SHA256Digest; import org.spongycastle.crypto.generators.ECKeyPairGenerator; import org.spongycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.ECKeyGenerationParameters; @@ -83,7 +83,7 @@ public class EllipticCurvePerformanceTest { List<byte[]> signatures = new ArrayList<byte[]>(); samples.clear(); for(int i = 0; i < SAMPLES; i++) { - Digest digest = new SHA384Digest(); + Digest digest = new SHA256Digest(); DSAKCalculator calculator = new HMacDSAKCalculator(digest); DSADigestSigner signer = new DSADigestSigner(new ECDSASigner( calculator), digest); @@ -97,7 +97,7 @@ public class EllipticCurvePerformanceTest { // Time some signature verifications samples.clear(); for(int i = 0; i < SAMPLES; i++) { - Digest digest = new SHA384Digest(); + Digest digest = new SHA256Digest(); DSAKCalculator calculator = new HMacDSAKCalculator(digest); DSADigestSigner signer = new DSADigestSigner(new ECDSASigner( calculator), digest); diff --git a/briar-tests/src/org/briarproject/messaging/ConsumersTest.java b/briar-tests/src/org/briarproject/messaging/ConsumersTest.java index ccf1038d22..f214336067 100644 --- a/briar-tests/src/org/briarproject/messaging/ConsumersTest.java +++ b/briar-tests/src/org/briarproject/messaging/ConsumersTest.java @@ -63,7 +63,7 @@ public class ConsumersTest extends BriarTestCase { private final java.security.MessageDigest delegate; private TestMessageDigest() throws GeneralSecurityException { - delegate = java.security.MessageDigest.getInstance("SHA-384"); + delegate = java.security.MessageDigest.getInstance("SHA-256"); } public byte[] digest() { @@ -99,6 +99,6 @@ public class ConsumersTest extends BriarTestCase { public void update(byte[] input, int offset, int len) { delegate.update(input, offset, len); - } + } } } -- GitLab