From 8bdf04a28924ec76c011e979331e393235068b6e Mon Sep 17 00:00:00 2001
From: akwizgran <michael@briarproject.org>
Date: Fri, 2 Feb 2018 22:13:28 +0000
Subject: [PATCH] Clamp private keys, add test vectors.

---
 .../bramble/crypto/Curve25519KeyParser.java   | 11 ++++++-
 .../bramble/crypto/KeyAgreementTest.java      | 32 +++++++++++++++++++
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/Curve25519KeyParser.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Curve25519KeyParser.java
index d7aeac26a2..e7b39ad8d3 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/Curve25519KeyParser.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Curve25519KeyParser.java
@@ -21,6 +21,15 @@ class Curve25519KeyParser implements KeyParser {
 	public PrivateKey parsePrivateKey(byte[] encodedKey)
 			throws GeneralSecurityException {
 		if (encodedKey.length != 32) throw new GeneralSecurityException();
-		return new Curve25519PrivateKey(encodedKey);
+		return new Curve25519PrivateKey(clamp(encodedKey));
+	}
+
+	static byte[] clamp(byte[] b) {
+		byte[] clamped = new byte[32];
+		System.arraycopy(b, 0, clamped, 0, 32);
+		clamped[0] &= 248;
+		clamped[31] &= 127;
+		clamped[31] |= 64;
+		return clamped;
 	}
 }
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyAgreementTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyAgreementTest.java
index a086046c36..f0505f4f13 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyAgreementTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyAgreementTest.java
@@ -7,16 +7,32 @@ import org.briarproject.bramble.api.crypto.SecretKey;
 import org.briarproject.bramble.test.BrambleTestCase;
 import org.briarproject.bramble.test.TestSecureRandomProvider;
 import org.junit.Test;
+import org.whispersystems.curve25519.Curve25519;
 
 import java.security.GeneralSecurityException;
 import java.util.Random;
 
 import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.SHARED_SECRET_LABEL;
 import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
+import static org.briarproject.bramble.util.StringUtils.fromHexString;
 import static org.junit.Assert.assertArrayEquals;
 
 public class KeyAgreementTest extends BrambleTestCase {
 
+	// Test vector from RFC 7748: Alice's private and public keys, Bob's
+	// private and public keys, and the shared secret
+	// https://tools.ietf.org/html/rfc7748#section-6.1
+	private static final String ALICE_PRIVATE =
+			"77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a";
+	private static final String ALICE_PUBLIC =
+			"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a";
+	private static final String BOB_PRIVATE =
+			"5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb";
+	private static final String BOB_PUBLIC =
+			"de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f";
+	private static final String SHARED_SECRET =
+			"4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742";
+
 	private final CryptoComponent crypto =
 			new CryptoComponentImpl(new TestSecureRandomProvider(), null);
 	private final byte[][] inputs;
@@ -46,4 +62,20 @@ public class KeyAgreementTest extends BrambleTestCase {
 		crypto.deriveSharedSecret(SHARED_SECRET_LABEL, invalid, keyPair,
 				inputs);
 	}
+
+	@Test
+	public void testRfc7748TestVector() throws Exception {
+		// Private keys need to be clamped because curve25519-java does the
+		// clamping at key generation time, not multiplication time
+		byte[] aPriv = Curve25519KeyParser.clamp(fromHexString(ALICE_PRIVATE));
+		byte[] aPub = fromHexString(ALICE_PUBLIC);
+		byte[] bPriv = Curve25519KeyParser.clamp(fromHexString(BOB_PRIVATE));
+		byte[] bPub = fromHexString(BOB_PUBLIC);
+		byte[] sharedSecret = fromHexString(SHARED_SECRET);
+		Curve25519 curve25519 = Curve25519.getInstance("java");
+		assertArrayEquals(sharedSecret,
+				curve25519.calculateAgreement(aPub, bPriv));
+		assertArrayEquals(sharedSecret,
+				curve25519.calculateAgreement(bPub, aPriv));
+	}
 }
-- 
GitLab