From 7545a1cc8f8d19b6f4be45898b83abe401162825 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Thu, 11 Aug 2011 19:14:20 +0100
Subject: [PATCH] Moved Bytes to the main package. Added a SharedSecret class
 to parse encrypted secrets retrieved from the database.

---
 api/net/sf/briar/api/{serial => }/Bytes.java  |  2 +-
 .../sf/briar/api/crypto/CryptoComponent.java  |  6 +--
 .../sf/briar/crypto/CryptoComponentImpl.java  | 36 ++++++++--------
 .../net/sf/briar/crypto/SharedSecret.java     | 42 +++++++++++++++++++
 .../net/sf/briar/serial/ReaderImpl.java       |  2 +-
 .../net/sf/briar/serial/WriterImpl.java       |  2 +-
 test/net/sf/briar/crypto/CounterModeTest.java |  2 +-
 test/net/sf/briar/serial/ReaderImplTest.java  |  2 +-
 8 files changed, 68 insertions(+), 26 deletions(-)
 rename api/net/sf/briar/api/{serial => }/Bytes.java (93%)
 create mode 100644 components/net/sf/briar/crypto/SharedSecret.java

diff --git a/api/net/sf/briar/api/serial/Bytes.java b/api/net/sf/briar/api/Bytes.java
similarity index 93%
rename from api/net/sf/briar/api/serial/Bytes.java
rename to api/net/sf/briar/api/Bytes.java
index e6ad5ee52e..77b82c1beb 100644
--- a/api/net/sf/briar/api/serial/Bytes.java
+++ b/api/net/sf/briar/api/Bytes.java
@@ -1,4 +1,4 @@
-package net.sf.briar.api.serial;
+package net.sf.briar.api;
 
 import java.util.Arrays;
 
diff --git a/api/net/sf/briar/api/crypto/CryptoComponent.java b/api/net/sf/briar/api/crypto/CryptoComponent.java
index 7684c549b1..a8f3530f45 100644
--- a/api/net/sf/briar/api/crypto/CryptoComponent.java
+++ b/api/net/sf/briar/api/crypto/CryptoComponent.java
@@ -10,11 +10,11 @@ import javax.crypto.SecretKey;
 
 public interface CryptoComponent {
 
-	SecretKey deriveMacKey(byte[] secret, boolean alice);
+	SecretKey deriveMacKey(byte[] secret);
 
-	SecretKey derivePacketKey(byte[] secret, boolean alice);
+	SecretKey derivePacketKey(byte[] secret);
 
-	SecretKey deriveTagKey(byte[] secret, boolean alice);
+	SecretKey deriveTagKey(byte[] secret);
 
 	KeyPair generateKeyPair();
 
diff --git a/components/net/sf/briar/crypto/CryptoComponentImpl.java b/components/net/sf/briar/crypto/CryptoComponentImpl.java
index c02a668a89..99cbe824d7 100644
--- a/components/net/sf/briar/crypto/CryptoComponentImpl.java
+++ b/components/net/sf/briar/crypto/CryptoComponentImpl.java
@@ -68,33 +68,31 @@ class CryptoComponentImpl implements CryptoComponent {
 		}
 	}
 
-	public SecretKey deriveMacKey(byte[] secret, boolean alice) {
-		if(alice) return deriveKey("MACA", secret);
-		else return deriveKey("MACB", secret);
+	public SecretKey deriveMacKey(byte[] secret) {
+		SharedSecret s = new SharedSecret(secret);
+		if(s.getAlice()) return deriveKey("MACA", s.getIv(), s.getCiphertext());
+		else return deriveKey("MACB", s.getIv(), s.getCiphertext());
 	}
 
-	private SecretKey deriveKey(String name, byte[] secret) {
+	private SecretKey deriveKey(String name, IvParameterSpec iv,
+			byte[] ciphertext) {
 		MessageDigest digest = getMessageDigest();
 		try {
 			digest.update(name.getBytes("UTF-8"));
 		} catch(UnsupportedEncodingException e) {
 			throw new RuntimeException(e);
 		}
-		byte[] decrypted = decryptSharedSecret(secret);
+		byte[] decrypted = decryptSharedSecret(iv, ciphertext);
 		digest.update(decrypted);
-		Arrays.fill(decrypted, (byte) 0);
+		Arrays.fill(decrypted, (byte) 0); // Destroy the plaintext secret
 		return new SecretKeySpec(digest.digest(), SECRET_KEY_ALGO);
 	}
 
-	private byte[] decryptSharedSecret(byte[] secret) {
-		// The first 16 bytes of the stored secret are the IV
-		if(secret.length <= 16) throw new IllegalArgumentException();
-		IvParameterSpec iv = new IvParameterSpec(secret, 0, 16);
+	private byte[] decryptSharedSecret(IvParameterSpec iv, byte[] ciphertext) {
 		try {
-			// Decrypt and return the remainder of the stored secret
 			Cipher c = Cipher.getInstance(SECRET_STORAGE_ALGO, PROVIDER);
 			c.init(Cipher.DECRYPT_MODE, secretStorageKey, iv);
-			return c.doFinal(secret, 16, secret.length - 16);
+			return c.doFinal(ciphertext);
 		} catch(BadPaddingException e) {
 			throw new RuntimeException(e);
 		} catch(IllegalBlockSizeException e) {
@@ -112,14 +110,16 @@ class CryptoComponentImpl implements CryptoComponent {
 		}
 	}
 
-	public SecretKey derivePacketKey(byte[] secret, boolean alice) {
-		if(alice) return deriveKey("PKTA", secret);
-		else return deriveKey("PKTB", secret);
+	public SecretKey derivePacketKey(byte[] secret) {
+		SharedSecret s = new SharedSecret(secret);
+		if(s.getAlice()) return deriveKey("PKTA", s.getIv(), s.getCiphertext());
+		else return deriveKey("PKTB", s.getIv(), s.getCiphertext());
 	}
 
-	public SecretKey deriveTagKey(byte[] secret, boolean alice) {
-		if(alice) return deriveKey("TAGA", secret);
-		else return deriveKey("TAGB", secret);
+	public SecretKey deriveTagKey(byte[] secret) {
+		SharedSecret s = new SharedSecret(secret);
+		if(s.getAlice()) return deriveKey("TAGA", s.getIv(), s.getCiphertext());
+		else return deriveKey("TAGB", s.getIv(), s.getCiphertext());
 	}
 
 	public KeyPair generateKeyPair() {
diff --git a/components/net/sf/briar/crypto/SharedSecret.java b/components/net/sf/briar/crypto/SharedSecret.java
new file mode 100644
index 0000000000..4e9eb747e3
--- /dev/null
+++ b/components/net/sf/briar/crypto/SharedSecret.java
@@ -0,0 +1,42 @@
+package net.sf.briar.crypto;
+
+import java.util.Arrays;
+
+import javax.crypto.spec.IvParameterSpec;
+
+class SharedSecret {
+
+	private static final int IV_BYTES = 16;
+
+	private final IvParameterSpec iv;
+	private final boolean alice;
+	private final byte[] ciphertext;
+
+	SharedSecret(byte[] secret) {
+		if(secret.length < IV_BYTES + 2) throw new IllegalArgumentException();
+		iv = new IvParameterSpec(secret, 0, IV_BYTES);
+		switch(secret[IV_BYTES]) {
+		case 0:
+			alice = false;
+			break;
+		case 1:
+			alice = true;
+			break;
+		default:
+			throw new IllegalArgumentException();
+		}
+		ciphertext = Arrays.copyOfRange(secret, IV_BYTES + 1, secret.length);
+	}
+
+	IvParameterSpec getIv() {
+		return iv;
+	}
+
+	boolean getAlice() {
+		return alice;
+	}
+
+	byte[] getCiphertext() {
+		return ciphertext;
+	}
+}
diff --git a/components/net/sf/briar/serial/ReaderImpl.java b/components/net/sf/briar/serial/ReaderImpl.java
index 9638998a97..92cb7a8652 100644
--- a/components/net/sf/briar/serial/ReaderImpl.java
+++ b/components/net/sf/briar/serial/ReaderImpl.java
@@ -8,7 +8,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import net.sf.briar.api.serial.Bytes;
+import net.sf.briar.api.Bytes;
 import net.sf.briar.api.serial.Consumer;
 import net.sf.briar.api.serial.FormatException;
 import net.sf.briar.api.serial.ObjectReader;
diff --git a/components/net/sf/briar/serial/WriterImpl.java b/components/net/sf/briar/serial/WriterImpl.java
index b6d3b5b6c6..f20b0c52e9 100644
--- a/components/net/sf/briar/serial/WriterImpl.java
+++ b/components/net/sf/briar/serial/WriterImpl.java
@@ -7,7 +7,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import net.sf.briar.api.serial.Bytes;
+import net.sf.briar.api.Bytes;
 import net.sf.briar.api.serial.Tag;
 import net.sf.briar.api.serial.Writable;
 import net.sf.briar.api.serial.Writer;
diff --git a/test/net/sf/briar/crypto/CounterModeTest.java b/test/net/sf/briar/crypto/CounterModeTest.java
index 176296af9d..7ce6dbcc29 100644
--- a/test/net/sf/briar/crypto/CounterModeTest.java
+++ b/test/net/sf/briar/crypto/CounterModeTest.java
@@ -11,7 +11,7 @@ import javax.crypto.spec.IvParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
 
 import junit.framework.TestCase;
-import net.sf.briar.api.serial.Bytes;
+import net.sf.briar.api.Bytes;
 
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.junit.Test;
diff --git a/test/net/sf/briar/serial/ReaderImplTest.java b/test/net/sf/briar/serial/ReaderImplTest.java
index efe4866c0e..2187e67bf7 100644
--- a/test/net/sf/briar/serial/ReaderImplTest.java
+++ b/test/net/sf/briar/serial/ReaderImplTest.java
@@ -9,10 +9,10 @@ import java.util.Map;
 import java.util.Map.Entry;
 
 import junit.framework.TestCase;
+import net.sf.briar.api.Bytes;
 import net.sf.briar.api.serial.Consumer;
 import net.sf.briar.api.serial.FormatException;
 import net.sf.briar.api.serial.ObjectReader;
-import net.sf.briar.api.serial.Bytes;
 import net.sf.briar.api.serial.Reader;
 import net.sf.briar.util.StringUtils;
 
-- 
GitLab