From 27c4306e0382d5073e96560be3f9d16c0080a951 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Sun, 24 Nov 2013 15:11:46 +0000
Subject: [PATCH] Switched from NIST curve P-384 to RFC 5639 curve
 brainpoolP384r1.

---
 .../src/net/sf/briar/api/AuthorConstants.java | 22 +++++-
 .../sf/briar/crypto/CryptoComponentImpl.java  | 10 +--
 .../briar/crypto/EllipticCurveConstants.java  | 70 +++++++++++++++++++
 .../net/sf/briar/crypto/P384Constants.java    | 41 -----------
 .../net/sf/briar/crypto/Sec1KeyParser.java    |  3 +-
 .../net/sf/briar/messaging/ConstantsTest.java |  3 +-
 6 files changed, 99 insertions(+), 50 deletions(-)
 create mode 100644 briar-core/src/net/sf/briar/crypto/EllipticCurveConstants.java
 delete mode 100644 briar-core/src/net/sf/briar/crypto/P384Constants.java

diff --git a/briar-api/src/net/sf/briar/api/AuthorConstants.java b/briar-api/src/net/sf/briar/api/AuthorConstants.java
index f9a358d8a4..507b63e615 100644
--- a/briar-api/src/net/sf/briar/api/AuthorConstants.java
+++ b/briar-api/src/net/sf/briar/api/AuthorConstants.java
@@ -5,9 +5,27 @@ public interface AuthorConstants {
 	/** The maximum length of an author's name in UTF-8 bytes. */
 	int MAX_AUTHOR_NAME_LENGTH = 50;
 
-	/** The maximum length of a public key in bytes. */
+	/**
+	 * The maximum length of a public key in bytes.
+	 * <p>
+	 * 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.
+	 */
 	int MAX_PUBLIC_KEY_LENGTH = 97;
 
-	/** The maximum length of a signature in bytes. */
+	/**
+	 * The maximum length of a signature in bytes.
+	 * <p>
+	 * A signature is an ASN.1 DER sequence containing two integers, r and s.
+	 * The format is 0x30 len1 0x02 len2 r 0x02 len3 s, where len1 is
+	 * len(0x02 len2 r 0x02 len3 s) as a DER length, len2 is len(r) as a DER
+	 * 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.
+	 */
 	int MAX_SIGNATURE_LENGTH = 104;
 }
diff --git a/briar-core/src/net/sf/briar/crypto/CryptoComponentImpl.java b/briar-core/src/net/sf/briar/crypto/CryptoComponentImpl.java
index 6cbf8b2349..6d701dbb5f 100644
--- a/briar-core/src/net/sf/briar/crypto/CryptoComponentImpl.java
+++ b/briar-core/src/net/sf/briar/crypto/CryptoComponentImpl.java
@@ -4,8 +4,8 @@ import static javax.crypto.Cipher.DECRYPT_MODE;
 import static javax.crypto.Cipher.ENCRYPT_MODE;
 import static net.sf.briar.api.invitation.InvitationConstants.CODE_BITS;
 import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
-import static net.sf.briar.crypto.P384Constants.P_384_PARAMS;
-import static net.sf.briar.crypto.P384Constants.P_384_Q;
+import static net.sf.briar.crypto.EllipticCurveConstants.PARAMETERS;
+import static net.sf.briar.crypto.EllipticCurveConstants.P;
 import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
 
 import java.io.ByteArrayOutputStream;
@@ -82,13 +82,13 @@ class CryptoComponentImpl implements CryptoComponent {
 	private final ECKeyPairGenerator signatureKeyPairGenerator;
 
 	CryptoComponentImpl() {
-		agreementKeyParser = new Sec1KeyParser(P_384_PARAMS, P_384_Q,
+		agreementKeyParser = new Sec1KeyParser(PARAMETERS, P,
 				AGREEMENT_KEY_PAIR_BITS);
-		signatureKeyParser = new Sec1KeyParser(P_384_PARAMS, P_384_Q,
+		signatureKeyParser = new Sec1KeyParser(PARAMETERS, P,
 				SIGNATURE_KEY_PAIR_BITS);
 		secureRandom = new SecureRandom();
 		ECKeyGenerationParameters params = new ECKeyGenerationParameters(
-				P_384_PARAMS, secureRandom);
+				PARAMETERS, secureRandom);
 		agreementKeyPairGenerator = new ECKeyPairGenerator();
 		agreementKeyPairGenerator.init(params);
 		signatureKeyPairGenerator = new ECKeyPairGenerator();
diff --git a/briar-core/src/net/sf/briar/crypto/EllipticCurveConstants.java b/briar-core/src/net/sf/briar/crypto/EllipticCurveConstants.java
new file mode 100644
index 0000000000..0c98783d9e
--- /dev/null
+++ b/briar-core/src/net/sf/briar/crypto/EllipticCurveConstants.java
@@ -0,0 +1,70 @@
+package net.sf.briar.crypto;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+
+/** 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);
+	ECPoint G = new ECPoint.Fp(CURVE,
+			new ECFieldElement.Fp(P, X),
+			new ECFieldElement.Fp(P, Y));
+	ECDomainParameters PARAMETERS = new ECDomainParameters(CURVE, G, Q, H);
+}
diff --git a/briar-core/src/net/sf/briar/crypto/P384Constants.java b/briar-core/src/net/sf/briar/crypto/P384Constants.java
deleted file mode 100644
index 067dc6dcd2..0000000000
--- a/briar-core/src/net/sf/briar/crypto/P384Constants.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package net.sf.briar.crypto;
-
-import java.math.BigInteger;
-
-import org.spongycastle.crypto.params.ECDomainParameters;
-import org.spongycastle.math.ec.ECCurve;
-import org.spongycastle.math.ec.ECFieldElement;
-import org.spongycastle.math.ec.ECPoint;
-
-interface P384Constants {
-
-	// Parameters for NIST elliptic curve P-384 - see "Suite B Implementer's
-	// Guide to NIST SP 800-56A", section A.2
-	BigInteger P_384_Q = new BigInteger("FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" +
-			"FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFE" +
-			"FFFFFFFF" + "00000000" + "00000000" + "FFFFFFFF", 16);
-	BigInteger P_384_A = new BigInteger("FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" +
-			"FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFE" +
-			"FFFFFFFF" + "00000000" + "00000000" + "FFFFFFFC", 16);
-	BigInteger P_384_B = new BigInteger("B3312FA7" + "E23EE7E4" + "988E056B" +
-			"E3F82D19" + "181D9C6E" + "FE814112" + "0314088F" + "5013875A" +
-			"C656398D" + "8A2ED19D" + "2A85C8ED" + "D3EC2AEF", 16);
-	BigInteger P_384_G_X = new BigInteger("AA87CA22" + "BE8B0537" + "8EB1C71E" +
-			"F320AD74" + "6E1D3B62" + "8BA79B98" + "59F741E0" + "82542A38" +
-			"5502F25D" + "BF55296C" + "3A545E38" + "72760AB7", 16);
-	BigInteger P_384_G_Y = new BigInteger("3617DE4A" + "96262C6F" + "5D9E98BF" +
-			"9292DC29" + "F8F41DBD" + "289A147C" + "E9DA3113" + "B5F0B8C0" +
-			"0A60B1CE" + "1D7E819D" + "7A431D7C" + "90EA0E5F", 16);
-	BigInteger P_384_N = new BigInteger("FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" +
-			"FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "C7634D81" + "F4372DDF" +
-			"581A0DB2" + "48B0A77A" + "ECEC196A" + "CCC52973", 16);
-	BigInteger P_384_H = BigInteger.ONE;
-
-	// Static parameter objects derived from the above parameters
-	ECCurve P_384_CURVE = new ECCurve.Fp(P_384_Q, P_384_A, P_384_B);
-	ECPoint P_384_G = new ECPoint.Fp(P_384_CURVE,
-			new ECFieldElement.Fp(P_384_Q, P_384_G_X),
-			new ECFieldElement.Fp(P_384_Q, P_384_G_Y));
-	ECDomainParameters P_384_PARAMS = new ECDomainParameters(P_384_CURVE,
-			P_384_G, P_384_N, P_384_H);
-}
diff --git a/briar-core/src/net/sf/briar/crypto/Sec1KeyParser.java b/briar-core/src/net/sf/briar/crypto/Sec1KeyParser.java
index 915fcbd9cd..522a5543aa 100644
--- a/briar-core/src/net/sf/briar/crypto/Sec1KeyParser.java
+++ b/briar-core/src/net/sf/briar/crypto/Sec1KeyParser.java
@@ -35,6 +35,7 @@ class Sec1KeyParser implements KeyParser {
 
 	public PublicKey parsePublicKey(byte[] encodedKey)
 			throws GeneralSecurityException {
+		// Note: SEC 1 parameter names are used below, not RFC 5639 names
 		if(encodedKey.length != publicKeyBytes)
 			throw new GeneralSecurityException();
 		// The first byte must be 0x04
@@ -49,7 +50,7 @@ class Sec1KeyParser implements KeyParser {
 		System.arraycopy(encodedKey, bytesPerInt + 1, yBytes, 0, bytesPerInt);
 		BigInteger y = new BigInteger(1, yBytes); // Positive signum
 		if(y.compareTo(modulus) >= 0) throw new GeneralSecurityException();
-		// Verify that y^2 == x^3 + ax + b (mod q)
+		// Verify that y^2 == x^3 + ax + b (mod p)
 		BigInteger a = params.getCurve().getA().toBigInteger();
 		BigInteger b = params.getCurve().getB().toBigInteger();
 		BigInteger lhs = y.multiply(y).mod(modulus);
diff --git a/briar-tests/src/net/sf/briar/messaging/ConstantsTest.java b/briar-tests/src/net/sf/briar/messaging/ConstantsTest.java
index 93871605ec..db00cdebd5 100644
--- a/briar-tests/src/net/sf/briar/messaging/ConstantsTest.java
+++ b/briar-tests/src/net/sf/briar/messaging/ConstantsTest.java
@@ -101,7 +101,8 @@ public class ConstantsTest extends BriarTestCase {
 			sig.initSign(keyPair.getPrivate());
 			sig.update(toBeSigned);
 			byte[] signature = sig.sign();
-			assertTrue(signature.length <= MAX_SIGNATURE_LENGTH);
+			assertTrue("Length " + signature.length,
+					signature.length <= MAX_SIGNATURE_LENGTH);
 		}
 	}
 
-- 
GitLab