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 e6ad5ee52e46f3ba0afefeb9746f7cb1184952bb..77b82c1beb95763c421afc20364f6f6ce3a9f4f0 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 7684c549b1bfa6f2d01b56be43f848c961bef97c..a8f3530f459e442954af5cb4d81bb17bb85dbb95 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 c02a668a894c8a7de9dd41bb2ec87f01c53f677a..99cbe824d79198553fb776de824c274c44d836b4 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 0000000000000000000000000000000000000000..4e9eb747e3df15ea548ed387764f4828028e6f08 --- /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 9638998a9767cc00d535064679863711cbc62947..92cb7a8652fc0b8d3afe3926cc77652126b4df43 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 b6d3b5b6c699d354a463d7c2bfb25e8eadbaca1a..f20b0c52e9d29603c0cb2cedc12d83aba15ff646 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 176296af9dafd14ae995861cdf0ddd5ffce1e1ae..7ce6dbcc29515fb98e09f59a458c2bad2ba50385 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 efe4866c0e9a8a03df29535a8e456ee513a8ca62..2187e67bf74764ac9ae6e83a8e9975899ab12e71 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;