From 90af1768107ce2133dbcb20b8a2e66ff99a55835 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Thu, 31 Dec 2015 17:42:11 +0000
Subject: [PATCH] Use BLAKE2s for hashing, key derivation and signatures.

SHA-256 is still used for password-based key derivation (will be replaced with Argon2) and Fortuna.
---
 .../crypto/CryptoComponentImpl.java           | 12 ++--
 .../briarproject/crypto/DigestWrapper.java    | 58 +++++++++++++++++++
 .../org/briarproject/crypto/DoubleDigest.java |  9 ---
 .../briarproject/crypto/SignatureImpl.java    | 15 +++--
 .../crypto/EllipticCurvePerformanceTest.java  |  5 +-
 5 files changed, 71 insertions(+), 28 deletions(-)
 create mode 100644 briar-core/src/org/briarproject/crypto/DigestWrapper.java

diff --git a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
index e88e42ea36..9735016993 100644
--- a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
+++ b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
@@ -20,14 +20,11 @@ import org.spongycastle.crypto.AsymmetricCipherKeyPair;
 import org.spongycastle.crypto.BlockCipher;
 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.Blake2bDigest;
 import org.spongycastle.crypto.digests.SHA256Digest;
 import org.spongycastle.crypto.engines.AESLightEngine;
 import org.spongycastle.crypto.generators.ECKeyPairGenerator;
 import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator;
-import org.spongycastle.crypto.macs.HMac;
 import org.spongycastle.crypto.params.ECKeyGenerationParameters;
 import org.spongycastle.crypto.params.ECPrivateKeyParameters;
 import org.spongycastle.crypto.params.ECPublicKeyParameters;
@@ -123,7 +120,7 @@ class CryptoComponentImpl implements CryptoComponent {
 	}
 
 	public MessageDigest getMessageDigest() {
-		return new DoubleDigest(new SHA256Digest());
+		return new DigestWrapper(new Blake2sDigest());
 	}
 
 	public PseudoRandom getPseudoRandom(int seed1, int seed2) {
@@ -390,7 +387,7 @@ class CryptoComponentImpl implements CryptoComponent {
 	// Key derivation function based on a hash function - see NIST SP 800-56A,
 	// section 5.8
 	private byte[] hashKdf(byte[]... inputs) {
-		Digest digest = new Blake2bDigest();
+		Digest digest = new Blake2sDigest();
 		// The output of the hash function must be long enough to use as a key
 		int hashLength = digest.getDigestSize();
 		if (hashLength < SecretKey.LENGTH) throw new IllegalStateException();
@@ -414,10 +411,9 @@ class CryptoComponentImpl implements CryptoComponent {
 	// NIST SP 800-108, section 5.1
 	private byte[] macKdf(SecretKey key, byte[]... inputs) {
 		// Initialise the PRF
-		Mac prf = new HMac(new Blake2bDigest());
-		prf.init(new KeyParameter(key.getBytes()));
+		Digest prf = new Blake2sDigest(key.getBytes());
 		// The output of the PRF must be long enough to use as a key
-		int macLength = prf.getMacSize();
+		int macLength = prf.getDigestSize();
 		if (macLength < SecretKey.LENGTH) throw new IllegalStateException();
 		// Calculate the PRF over the concatenated length-prefixed inputs
 		byte[] length = new byte[4];
diff --git a/briar-core/src/org/briarproject/crypto/DigestWrapper.java b/briar-core/src/org/briarproject/crypto/DigestWrapper.java
new file mode 100644
index 0000000000..30b623eee3
--- /dev/null
+++ b/briar-core/src/org/briarproject/crypto/DigestWrapper.java
@@ -0,0 +1,58 @@
+package org.briarproject.crypto;
+
+import org.briarproject.api.crypto.MessageDigest;
+import org.spongycastle.crypto.Digest;
+
+class DigestWrapper implements MessageDigest {
+
+	private final Digest digest;
+
+	DigestWrapper(Digest digest) {
+		this.digest = digest;
+	}
+
+	@Override
+	public byte[] digest() {
+		byte[] hash = new byte[digest.getDigestSize()];
+		digest.doFinal(hash, 0);
+		return hash;
+	}
+
+	@Override
+	public byte[] digest(byte[] input) {
+		update(input);
+		return digest();
+	}
+
+	@Override
+	public int digest(byte[] buf, int offset, int len) {
+		if (len != digest.getDigestSize()) throw new IllegalArgumentException();
+		digest.doFinal(buf, offset);
+		return len;
+	}
+
+	@Override
+	public int getDigestLength() {
+		return digest.getDigestSize();
+	}
+
+	@Override
+	public void reset() {
+		digest.reset();
+	}
+
+	@Override
+	public void update(byte input) {
+		digest.update(input);
+	}
+
+	@Override
+	public void update(byte[] input) {
+		digest.update(input, 0, input.length);
+	}
+
+	@Override
+	public void update(byte[] input, int offset, int len) {
+		digest.update(input, offset, len);
+	}
+}
diff --git a/briar-core/src/org/briarproject/crypto/DoubleDigest.java b/briar-core/src/org/briarproject/crypto/DoubleDigest.java
index 1d1fdd99d1..a8670a2171 100644
--- a/briar-core/src/org/briarproject/crypto/DoubleDigest.java
+++ b/briar-core/src/org/briarproject/crypto/DoubleDigest.java
@@ -3,15 +3,6 @@ package org.briarproject.crypto;
 import org.briarproject.api.crypto.MessageDigest;
 import org.spongycastle.crypto.Digest;
 
-/**
- * A message digest that prevents length extension attacks - see Ferguson and
- * Schneier, <i>Practical Cryptography</i>, chapter 6.
- * <p>
- * "Let h be an interative hash function. The hash function h<sub>d</sub> is
- * defined by h<sub>d</sub> := h(h(m)), and has a claimed security level of
- * min(k, n/2) where k is the security level of h and n is the size of the hash
- * result."
- */
 class DoubleDigest implements MessageDigest {
 
 	private final Digest delegate;
diff --git a/briar-core/src/org/briarproject/crypto/SignatureImpl.java b/briar-core/src/org/briarproject/crypto/SignatureImpl.java
index dd79b8b4c9..ebed171edd 100644
--- a/briar-core/src/org/briarproject/crypto/SignatureImpl.java
+++ b/briar-core/src/org/briarproject/crypto/SignatureImpl.java
@@ -1,16 +1,9 @@
 package org.briarproject.crypto;
 
-import static java.util.logging.Level.INFO;
-
-import java.security.GeneralSecurityException;
-import java.security.SecureRandom;
-import java.util.logging.Logger;
-
 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.SHA256Digest;
 import org.spongycastle.crypto.params.ECPrivateKeyParameters;
 import org.spongycastle.crypto.params.ECPublicKeyParameters;
 import org.spongycastle.crypto.params.ParametersWithRandom;
@@ -19,6 +12,12 @@ import org.spongycastle.crypto.signers.DSAKCalculator;
 import org.spongycastle.crypto.signers.ECDSASigner;
 import org.spongycastle.crypto.signers.HMacDSAKCalculator;
 
+import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
+import java.util.logging.Logger;
+
+import static java.util.logging.Level.INFO;
+
 class SignatureImpl implements Signature {
 
 	private static final Logger LOG =
@@ -29,7 +28,7 @@ class SignatureImpl implements Signature {
 
 	SignatureImpl(SecureRandom secureRandom) {
 		this.secureRandom = secureRandom;
-		Digest digest = new SHA256Digest();
+		Digest digest = new Blake2sDigest();
 		DSAKCalculator calculator = new HMacDSAKCalculator(digest);
 		signer = new DSADigestSigner(new ECDSASigner(calculator), digest);
 	}
diff --git a/briar-tests/src/org/briarproject/crypto/EllipticCurvePerformanceTest.java b/briar-tests/src/org/briarproject/crypto/EllipticCurvePerformanceTest.java
index a9b10b0b9e..7f18689e84 100644
--- a/briar-tests/src/org/briarproject/crypto/EllipticCurvePerformanceTest.java
+++ b/briar-tests/src/org/briarproject/crypto/EllipticCurvePerformanceTest.java
@@ -6,7 +6,6 @@ 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.SHA256Digest;
 import org.spongycastle.crypto.generators.ECKeyPairGenerator;
 import org.spongycastle.crypto.params.ECDomainParameters;
 import org.spongycastle.crypto.params.ECKeyGenerationParameters;
@@ -83,7 +82,7 @@ public class EllipticCurvePerformanceTest {
 		List<byte[]> signatures = new ArrayList<byte[]>();
 		samples.clear();
 		for (int i = 0; i < SAMPLES; i++) {
-			Digest digest = new SHA256Digest();
+			Digest digest = new Blake2sDigest();
 			DSAKCalculator calculator = new HMacDSAKCalculator(digest);
 			DSADigestSigner signer = new DSADigestSigner(new ECDSASigner(
 					calculator), digest);
@@ -97,7 +96,7 @@ public class EllipticCurvePerformanceTest {
 		// Time some signature verifications
 		samples.clear();
 		for (int i = 0; i < SAMPLES; i++) {
-			Digest digest = new SHA256Digest();
+			Digest digest = new Blake2sDigest();
 			DSAKCalculator calculator = new HMacDSAKCalculator(digest);
 			DSADigestSigner signer = new DSADigestSigner(new ECDSASigner(
 					calculator), digest);
-- 
GitLab