diff --git a/briar-android/src/net/sf/briar/android/SetupActivity.java b/briar-android/src/net/sf/briar/android/SetupActivity.java index 73dd6b6261917c928951596648684f9c04ff319c..14fc2bed19fc4f179512fefec256a5412e348dbe 100644 --- a/briar-android/src/net/sf/briar/android/SetupActivity.java +++ b/briar-android/src/net/sf/briar/android/SetupActivity.java @@ -13,7 +13,6 @@ import static net.sf.briar.android.util.CommonLayoutParams.MATCH_MATCH; import static net.sf.briar.android.util.CommonLayoutParams.WRAP_WRAP; import java.io.IOException; -import java.security.KeyPair; import java.util.Arrays; import java.util.concurrent.Executor; @@ -23,6 +22,7 @@ import net.sf.briar.api.LocalAuthor; import net.sf.briar.api.android.ReferenceManager; import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.CryptoExecutor; +import net.sf.briar.api.crypto.KeyPair; import net.sf.briar.api.db.DatabaseConfig; import net.sf.briar.util.StringUtils; import roboguice.activity.RoboActivity; diff --git a/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java b/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java index 00a4519dfefcad5d00a412216c326068c85d69ef..9f7cbeadeec7410980efbf288068f5c95c876cce 100644 --- a/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java +++ b/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java @@ -14,7 +14,6 @@ import static net.sf.briar.android.util.CommonLayoutParams.MATCH_MATCH; import static net.sf.briar.android.util.CommonLayoutParams.WRAP_WRAP; import java.io.IOException; -import java.security.KeyPair; import java.util.Collection; import java.util.Collections; import java.util.concurrent.Executor; @@ -29,6 +28,7 @@ import net.sf.briar.api.ContactId; import net.sf.briar.api.android.DatabaseUiExecutor; import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.CryptoExecutor; +import net.sf.briar.api.crypto.KeyPair; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DbException; import net.sf.briar.api.lifecycle.LifecycleManager; diff --git a/briar-android/src/net/sf/briar/android/blogs/WriteBlogPostActivity.java b/briar-android/src/net/sf/briar/android/blogs/WriteBlogPostActivity.java index d8885ffe34461406c063d6292e42a138c7790e2f..d28262c042c801d0fa1d30ecfecbe34e94189117 100644 --- a/briar-android/src/net/sf/briar/android/blogs/WriteBlogPostActivity.java +++ b/briar-android/src/net/sf/briar/android/blogs/WriteBlogPostActivity.java @@ -11,7 +11,6 @@ import static net.sf.briar.android.util.CommonLayoutParams.MATCH_WRAP; import java.io.IOException; import java.security.GeneralSecurityException; -import java.security.PrivateKey; import java.util.Collection; import java.util.concurrent.Executor; import java.util.logging.Logger; @@ -27,6 +26,7 @@ import net.sf.briar.api.LocalAuthor; import net.sf.briar.api.android.DatabaseUiExecutor; import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.KeyParser; +import net.sf.briar.api.crypto.PrivateKey; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DbException; import net.sf.briar.api.lifecycle.LifecycleManager; diff --git a/briar-android/src/net/sf/briar/android/groups/WriteGroupPostActivity.java b/briar-android/src/net/sf/briar/android/groups/WriteGroupPostActivity.java index d2bba879249ff600168aec3635715a9ffa755473..5c7b3ac37d8a7fe8baa459b02973a809ee035a9f 100644 --- a/briar-android/src/net/sf/briar/android/groups/WriteGroupPostActivity.java +++ b/briar-android/src/net/sf/briar/android/groups/WriteGroupPostActivity.java @@ -11,7 +11,6 @@ import static net.sf.briar.android.util.CommonLayoutParams.MATCH_WRAP; import java.io.IOException; import java.security.GeneralSecurityException; -import java.security.PrivateKey; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -30,6 +29,7 @@ import net.sf.briar.api.LocalAuthor; import net.sf.briar.api.android.DatabaseUiExecutor; import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.KeyParser; +import net.sf.briar.api.crypto.PrivateKey; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DbException; import net.sf.briar.api.lifecycle.LifecycleManager; diff --git a/briar-android/src/net/sf/briar/android/identity/CreateIdentityActivity.java b/briar-android/src/net/sf/briar/android/identity/CreateIdentityActivity.java index f89fff502b3ce5a6e99d9b12e406f0457e2b24a0..1df435f8d6b3bb956075762c83a4e93a38f83276 100644 --- a/briar-android/src/net/sf/briar/android/identity/CreateIdentityActivity.java +++ b/briar-android/src/net/sf/briar/android/identity/CreateIdentityActivity.java @@ -15,7 +15,6 @@ import static net.sf.briar.android.util.CommonLayoutParams.WRAP_WRAP; import static net.sf.briar.api.messaging.Rating.GOOD; import java.io.IOException; -import java.security.KeyPair; import java.util.concurrent.Executor; import java.util.logging.Logger; @@ -25,6 +24,7 @@ import net.sf.briar.api.LocalAuthor; import net.sf.briar.api.android.DatabaseUiExecutor; import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.CryptoExecutor; +import net.sf.briar.api.crypto.KeyPair; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DbException; import net.sf.briar.api.lifecycle.LifecycleManager; diff --git a/briar-api/src/net/sf/briar/api/crypto/AuthenticatedCipher.java b/briar-api/src/net/sf/briar/api/crypto/AuthenticatedCipher.java index 0dfa322af5e79bd872598e3408b0b511d12769fe..6105b70dc6f2fc231e4952dff6f090d7c183a3ac 100644 --- a/briar-api/src/net/sf/briar/api/crypto/AuthenticatedCipher.java +++ b/briar-api/src/net/sf/briar/api/crypto/AuthenticatedCipher.java @@ -1,28 +1,20 @@ package net.sf.briar.api.crypto; -import java.security.InvalidKeyException; -import java.security.Key; +import java.security.GeneralSecurityException; -import javax.crypto.BadPaddingException; -import javax.crypto.IllegalBlockSizeException; - -/** - * A wrapper for a provider-dependent cipher class, since javax.crypto.Cipher - * doesn't support additional authenticated data until Java 7. - */ +/** An authenticated cipher that support additional authenticated data. */ public interface AuthenticatedCipher { /** * Initializes this cipher with a key, an initialisation vector (IV) and * additional authenticated data (AAD). */ - void init(int opmode, Key key, byte[] iv, byte[] aad) - throws InvalidKeyException; + void init(int opmode, SecretKey key, byte[] iv, byte[] aad) + throws GeneralSecurityException; /** Encrypts or decrypts data in a single-part operation. */ int doFinal(byte[] input, int inputOff, int len, byte[] output, - int outputOff) throws IllegalBlockSizeException, - BadPaddingException; + int outputOff) throws GeneralSecurityException; /** Returns the length of the message authenticated code (MAC) in bytes. */ int getMacLength(); diff --git a/briar-api/src/net/sf/briar/api/crypto/CryptoComponent.java b/briar-api/src/net/sf/briar/api/crypto/CryptoComponent.java index a6ae9cbd3ac09b56541bdaeb3f23d8fda63d545f..baee643e92896ab1a0efb9b3f5ae43c706294bbc 100644 --- a/briar-api/src/net/sf/briar/api/crypto/CryptoComponent.java +++ b/briar-api/src/net/sf/briar/api/crypto/CryptoComponent.java @@ -1,13 +1,11 @@ package net.sf.briar.api.crypto; import java.security.GeneralSecurityException; -import java.security.KeyPair; import java.security.SecureRandom; -import java.security.Signature; public interface CryptoComponent { - ErasableKey generateSecretKey(); + SecretKey generateSecretKey(); MessageDigest getMessageDigest(); @@ -67,7 +65,7 @@ public interface CryptoComponent { * @param alice indicates whether the key is for connections initiated by * Alice or Bob. */ - ErasableKey deriveTagKey(byte[] secret, boolean alice); + SecretKey deriveTagKey(byte[] secret, boolean alice); /** * Derives a frame key from the given temporary secret and connection @@ -77,14 +75,14 @@ public interface CryptoComponent { * @param initiator indicates whether the key is for the initiator's or the * responder's side of the connection. */ - ErasableKey deriveFrameKey(byte[] secret, long connection, boolean alice, + SecretKey deriveFrameKey(byte[] secret, long connection, boolean alice, boolean initiator); /** Returns a cipher for encrypting and authenticating connections. */ AuthenticatedCipher getFrameCipher(); /** Encodes the pseudo-random tag that is used to recognise a connection. */ - void encodeTag(byte[] tag, ErasableKey tagKey, long connection); + void encodeTag(byte[] tag, SecretKey tagKey, long connection); /** * Encrypts and authenticates the given plaintext so it can be written to diff --git a/briar-api/src/net/sf/briar/api/crypto/ErasableKey.java b/briar-api/src/net/sf/briar/api/crypto/ErasableKey.java deleted file mode 100644 index 3503898ede179c0922a0e058f990c6441a83314e..0000000000000000000000000000000000000000 --- a/briar-api/src/net/sf/briar/api/crypto/ErasableKey.java +++ /dev/null @@ -1,12 +0,0 @@ -package net.sf.briar.api.crypto; - -import javax.crypto.SecretKey; - -public interface ErasableKey extends SecretKey { - - /** Returns a copy of the key. */ - ErasableKey copy(); - - /** Erases the key from memory. */ - void erase(); -} diff --git a/briar-api/src/net/sf/briar/api/crypto/KeyPair.java b/briar-api/src/net/sf/briar/api/crypto/KeyPair.java new file mode 100644 index 0000000000000000000000000000000000000000..76be830d717ef67292c4d5fa40e249b7194b8dd1 --- /dev/null +++ b/briar-api/src/net/sf/briar/api/crypto/KeyPair.java @@ -0,0 +1,21 @@ +package net.sf.briar.api.crypto; + +/** A key pair consisting of a {@link PublicKey} and a {@link PrivateKey). */ +public class KeyPair { + + private final PublicKey publicKey; + private final PrivateKey privateKey; + + public KeyPair(PublicKey publicKey, PrivateKey privateKey) { + this.publicKey = publicKey; + this.privateKey = privateKey; + } + + public PublicKey getPublic() { + return publicKey; + } + + public PrivateKey getPrivate() { + return privateKey; + } +} diff --git a/briar-api/src/net/sf/briar/api/crypto/KeyParser.java b/briar-api/src/net/sf/briar/api/crypto/KeyParser.java index da47281a822d2ed0144dd1548863986ac18e3517..835dcb3d736f01e146e95223a2ff207130422468 100644 --- a/briar-api/src/net/sf/briar/api/crypto/KeyParser.java +++ b/briar-api/src/net/sf/briar/api/crypto/KeyParser.java @@ -1,13 +1,11 @@ package net.sf.briar.api.crypto; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.spec.InvalidKeySpecException; +import java.security.GeneralSecurityException; public interface KeyParser { - PublicKey parsePublicKey(byte[] encodedKey) throws InvalidKeySpecException; + PublicKey parsePublicKey(byte[] encodedKey) throws GeneralSecurityException; PrivateKey parsePrivateKey(byte[] encodedKey) - throws InvalidKeySpecException; + throws GeneralSecurityException; } diff --git a/briar-api/src/net/sf/briar/api/crypto/MessageDigest.java b/briar-api/src/net/sf/briar/api/crypto/MessageDigest.java index 3855da89295be46d936fd2e8f92f7527150d4e52..406bd5dc74ee8ce02f02f1f5f7c393b68957c250 100644 --- a/briar-api/src/net/sf/briar/api/crypto/MessageDigest.java +++ b/briar-api/src/net/sf/briar/api/crypto/MessageDigest.java @@ -1,9 +1,5 @@ package net.sf.briar.api.crypto; -/** - * A wrapper around a {@link java.security.MessageDigest} that allows it to be - * replaced for testing. - */ public interface MessageDigest { /** @see {@link java.security.MessageDigest#digest()} */ diff --git a/briar-api/src/net/sf/briar/api/crypto/PrivateKey.java b/briar-api/src/net/sf/briar/api/crypto/PrivateKey.java new file mode 100644 index 0000000000000000000000000000000000000000..332bf906c867f0cf3d57c9ea27a796ea67fe9e18 --- /dev/null +++ b/briar-api/src/net/sf/briar/api/crypto/PrivateKey.java @@ -0,0 +1,8 @@ +package net.sf.briar.api.crypto; + +/** The private half of a public/private {@link KeyPair}. */ +public interface PrivateKey { + + /** Returns the encoded representation of this key. */ + byte[] getEncoded(); +} diff --git a/briar-api/src/net/sf/briar/api/crypto/PublicKey.java b/briar-api/src/net/sf/briar/api/crypto/PublicKey.java new file mode 100644 index 0000000000000000000000000000000000000000..27b851cf6ba3de8f5ddcee777f11278987c02b98 --- /dev/null +++ b/briar-api/src/net/sf/briar/api/crypto/PublicKey.java @@ -0,0 +1,8 @@ +package net.sf.briar.api.crypto; + +/** The public half of a public/private {@link KeyPair}. */ +public interface PublicKey { + + /** Returns the encoded representation of this key. */ + byte[] getEncoded(); +} diff --git a/briar-api/src/net/sf/briar/api/crypto/SecretKey.java b/briar-api/src/net/sf/briar/api/crypto/SecretKey.java new file mode 100644 index 0000000000000000000000000000000000000000..1149ae75399e511abf872078d830bf6384cb211d --- /dev/null +++ b/briar-api/src/net/sf/briar/api/crypto/SecretKey.java @@ -0,0 +1,21 @@ +package net.sf.briar.api.crypto; + +/** A secret key used for encryption and/or authentication. */ +public interface SecretKey { + + /** Returns the encoded representation of this key. */ + byte[] getEncoded(); + + /** + * Returns a copy of this key - erasing this key will erase the copy and + * vice versa. + */ + SecretKey copy(); + + /** + * Erases this key from memory. Any copies derived from this key via the + * {@link #copy()} method, and any keys from which this key was derived via + * the {@link #copy()} method, are also erased. + */ + void erase(); +} diff --git a/briar-api/src/net/sf/briar/api/crypto/Signature.java b/briar-api/src/net/sf/briar/api/crypto/Signature.java new file mode 100644 index 0000000000000000000000000000000000000000..f09595608b85f5d8b0a7f8a814cbaa380119cd85 --- /dev/null +++ b/briar-api/src/net/sf/briar/api/crypto/Signature.java @@ -0,0 +1,31 @@ +package net.sf.briar.api.crypto; + +import java.security.GeneralSecurityException; + +public interface Signature { + + /** + * @see {@link java.security.Signature#initSign(java.security.PrivateKey)} + */ + void initSign(PrivateKey k) throws GeneralSecurityException; + + /** + * @see {@link java.security.Signature#initVafiry(java.security.PublicKey)} + */ + void initVerify(PublicKey k) throws GeneralSecurityException; + + /** @see {@link java.security.Signature#update(byte)} */ + void update(byte b); + + /** @see {@link java.security.Signature#update(byte[])} */ + void update(byte[] b); + + /** @see {@link java.security.Signature#update(byte[], int, int)} */ + void update(byte[] b, int off, int len); + + /** @see {@link java.security.Signature#sign()} */ + byte[] sign(); + + /** @see {@link java.security.Signature#verify(byte[])} */ + boolean verify(byte[] signature); +} diff --git a/briar-api/src/net/sf/briar/api/messaging/MessageFactory.java b/briar-api/src/net/sf/briar/api/messaging/MessageFactory.java index a18b24df92f1387528ec99a470740719209ab6b0..4704d319d0bdafd51cdd9a37092db4f74d955fd5 100644 --- a/briar-api/src/net/sf/briar/api/messaging/MessageFactory.java +++ b/briar-api/src/net/sf/briar/api/messaging/MessageFactory.java @@ -2,9 +2,9 @@ package net.sf.briar.api.messaging; import java.io.IOException; import java.security.GeneralSecurityException; -import java.security.PrivateKey; import net.sf.briar.api.Author; +import net.sf.briar.api.crypto.PrivateKey; public interface MessageFactory { diff --git a/briar-api/src/net/sf/briar/api/serial/SigningConsumer.java b/briar-api/src/net/sf/briar/api/serial/SigningConsumer.java index e370317725eb5cd3e86e3e5c9fe6a5f544ccc2df..871d009263bb22c814eeec2358bfe061dab8603e 100644 --- a/briar-api/src/net/sf/briar/api/serial/SigningConsumer.java +++ b/briar-api/src/net/sf/briar/api/serial/SigningConsumer.java @@ -1,8 +1,6 @@ package net.sf.briar.api.serial; -import java.io.IOException; -import java.security.Signature; -import java.security.SignatureException; +import net.sf.briar.api.crypto.Signature; /** A consumer that passes its input through a signature. */ public class SigningConsumer implements Consumer { @@ -13,19 +11,11 @@ public class SigningConsumer implements Consumer { this.signature = signature; } - public void write(byte b) throws IOException { - try { - signature.update(b); - } catch(SignatureException e) { - throw new IOException(e.toString()); - } + public void write(byte b) { + signature.update(b); } - public void write(byte[] b, int off, int len) throws IOException { - try { - signature.update(b, off, len); - } catch(SignatureException e) { - throw new IOException(e.toString()); - } + public void write(byte[] b, int off, int len) { + signature.update(b, off, len); } } diff --git a/briar-core/.classpath b/briar-core/.classpath index 86223b4428bcc3abb1c073ee13f09efd751f2fdf..60b3f548e5ae3922884a29707d4458eadebde45a 100644 --- a/briar-core/.classpath +++ b/briar-core/.classpath @@ -6,7 +6,6 @@ <classpathentry kind="lib" path="libs/jnotify-0.93.jar"/> <classpathentry kind="lib" path="libs/jssc-0.9-briar.jar" sourcepath="libs/source/jssc-0.9-briar-source.jar"/> <classpathentry kind="lib" path="libs/sc-light-jdk15on-1.47.0.3-SNAPSHOT.jar" sourcepath="libs/source/sc-light-jdk15on-1.47.0.3-SNAPSHOT-source.jar"/> - <classpathentry kind="lib" path="libs/scprov-jdk15on-1.47.0.3-SNAPSHOT.jar" sourcepath="libs/source/scprov-jdk15on-1.47.0.3-SNAPSHOT-source.jar"/> <classpathentry kind="lib" path="libs/weupnp-0.1.1.jar"/> <classpathentry kind="lib" path="libs/bluecove-2.1.1-SNAPSHOT-briar.jar"/> <classpathentry kind="lib" path="libs/bluecove-gpl-2.1.1-SNAPSHOT.jar"/> diff --git a/briar-core/libs/scprov-jdk15on-1.47.0.3-SNAPSHOT.jar b/briar-core/libs/scprov-jdk15on-1.47.0.3-SNAPSHOT.jar deleted file mode 100644 index 4433cbb9589a4849281d51aaef404551d660974e..0000000000000000000000000000000000000000 Binary files a/briar-core/libs/scprov-jdk15on-1.47.0.3-SNAPSHOT.jar and /dev/null differ diff --git a/briar-core/src/net/sf/briar/crypto/AuthenticatedCipherImpl.java b/briar-core/src/net/sf/briar/crypto/AuthenticatedCipherImpl.java index 57d39f792df5672a6a380020b0f5a8c90c76b786..4597ebd34a54c7fb602a7327cc6de1c95c700cf5 100644 --- a/briar-core/src/net/sf/briar/crypto/AuthenticatedCipherImpl.java +++ b/briar-core/src/net/sf/briar/crypto/AuthenticatedCipherImpl.java @@ -1,13 +1,11 @@ package net.sf.briar.crypto; -import java.security.InvalidKeyException; -import java.security.Key; +import java.security.GeneralSecurityException; -import javax.crypto.BadPaddingException; import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; import net.sf.briar.api.crypto.AuthenticatedCipher; +import net.sf.briar.api.crypto.SecretKey; import org.spongycastle.crypto.DataLengthException; import org.spongycastle.crypto.InvalidCipherTextException; @@ -26,8 +24,7 @@ class AuthenticatedCipherImpl implements AuthenticatedCipher { } public int doFinal(byte[] input, int inputOff, int len, byte[] output, - int outputOff) throws IllegalBlockSizeException, - BadPaddingException { + int outputOff) throws GeneralSecurityException { int processed = 0; if(len != 0) { processed = cipher.processBytes(input, inputOff, len, output, @@ -36,14 +33,14 @@ class AuthenticatedCipherImpl implements AuthenticatedCipher { try { return processed + cipher.doFinal(output, outputOff + processed); } catch(DataLengthException e) { - throw new IllegalBlockSizeException(e.getMessage()); + throw new GeneralSecurityException(e.getMessage()); } catch(InvalidCipherTextException e) { - throw new BadPaddingException(e.getMessage()); + throw new GeneralSecurityException(e.getMessage()); } } - public void init(int opmode, Key key, byte[] iv, byte[] aad) - throws InvalidKeyException { + public void init(int opmode, SecretKey key, byte[] iv, byte[] aad) + throws GeneralSecurityException { KeyParameter k = new KeyParameter(key.getEncoded()); AEADParameters params = new AEADParameters(k, macLength * 8, iv, aad); try { @@ -59,8 +56,8 @@ class AuthenticatedCipherImpl implements AuthenticatedCipher { default: throw new IllegalArgumentException(); } - } catch(Exception e) { - throw new InvalidKeyException(e.getMessage()); + } catch(IllegalArgumentException e) { + throw new GeneralSecurityException(e.getMessage()); } } diff --git a/briar-core/src/net/sf/briar/crypto/CryptoComponentImpl.java b/briar-core/src/net/sf/briar/crypto/CryptoComponentImpl.java index da0a4b90bcbc2344f5026620118b7deac4fff3f5..4063ddf3ef93113831d6e63c5f7540850252a776 100644 --- a/briar-core/src/net/sf/briar/crypto/CryptoComponentImpl.java +++ b/briar-core/src/net/sf/briar/crypto/CryptoComponentImpl.java @@ -1,72 +1,54 @@ package net.sf.briar.crypto; -import static java.util.logging.Level.INFO; 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.util.ByteUtils.MAX_32_BIT_UNSIGNED; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.math.BigInteger; import java.security.GeneralSecurityException; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.PrivateKey; -import java.security.PublicKey; import java.security.SecureRandom; -import java.security.Security; -import java.security.Signature; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.security.spec.ECField; -import java.security.spec.ECFieldFp; -import java.security.spec.ECParameterSpec; -import java.security.spec.ECPoint; -import java.security.spec.EllipticCurve; import java.util.Arrays; -import java.util.logging.Logger; - -import javax.crypto.KeyAgreement; import net.sf.briar.api.crypto.AuthenticatedCipher; import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.crypto.ErasableKey; +import net.sf.briar.api.crypto.KeyPair; import net.sf.briar.api.crypto.KeyParser; import net.sf.briar.api.crypto.MessageDigest; +import net.sf.briar.api.crypto.PrivateKey; import net.sf.briar.api.crypto.PseudoRandom; +import net.sf.briar.api.crypto.PublicKey; +import net.sf.briar.api.crypto.SecretKey; +import net.sf.briar.api.crypto.Signature; import net.sf.briar.util.ByteUtils; +import org.spongycastle.crypto.AsymmetricCipherKeyPair; import org.spongycastle.crypto.BlockCipher; import org.spongycastle.crypto.CipherParameters; +import org.spongycastle.crypto.agreement.ECDHCBasicAgreement; +import org.spongycastle.crypto.digests.SHA384Digest; import org.spongycastle.crypto.engines.AESFastEngine; +import org.spongycastle.crypto.generators.ECKeyPairGenerator; import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator; import org.spongycastle.crypto.modes.AEADBlockCipher; import org.spongycastle.crypto.modes.GCMBlockCipher; +import org.spongycastle.crypto.params.ECKeyGenerationParameters; +import org.spongycastle.crypto.params.ECPrivateKeyParameters; +import org.spongycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.crypto.params.KeyParameter; -import org.spongycastle.jcajce.provider.asymmetric.ec.KeyPairGeneratorSpi; -import org.spongycastle.jcajce.provider.digest.SHA384; -import org.spongycastle.jce.provider.BouncyCastleProvider; import org.spongycastle.util.Strings; class CryptoComponentImpl implements CryptoComponent { - private static final Logger LOG = - Logger.getLogger(CryptoComponentImpl.class.getName()); - - private static final String PROVIDER = "SC"; // Spongy Castle - private static final String CIPHER_ALGO = "AES"; private static final int CIPHER_BLOCK_BYTES = 16; // 128 bits private static final int CIPHER_KEY_BYTES = 32; // 256 bits - private static final String AGREEMENT_ALGO = "ECDHC"; - private static final String AGREEMENT_KEY_PAIR_ALGO = "ECDH"; private static final int AGREEMENT_KEY_PAIR_BITS = 384; - private static final String SIGNATURE_ALGO = "ECDSA"; - private static final String SIGNATURE_KEY_PAIR_ALGO = "ECDSA"; private static final int SIGNATURE_KEY_PAIR_BITS = 384; - private static final int GCM_MAC_BYTES = 16; // 128 bits + private static final int MAC_BYTES = 16; // 128 bits private static final int STORAGE_IV_BYTES = 16; // 128 bits private static final int PBKDF_SALT_BYTES = 16; // 128 bits private static final int PBKDF_ITERATIONS = 1000; @@ -93,83 +75,33 @@ class CryptoComponentImpl implements CryptoComponent { // Blank secret for argument validation private static final byte[] BLANK_SECRET = new byte[CIPHER_KEY_BYTES]; - // Parameters for NIST elliptic curve P-384 - see "Suite B Implementer's - // Guide to NIST SP 800-56A", section A.2 - private static final BigInteger P_384_Q = new BigInteger("FFFFFFFF" + - "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + - "FFFFFFFF" + "FFFFFFFE" + "FFFFFFFF" + "00000000" + "00000000" + - "FFFFFFFF", 16); - private static final BigInteger P_384_A = new BigInteger("FFFFFFFF" + - "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + - "FFFFFFFF" + "FFFFFFFE" + "FFFFFFFF" + "00000000" + "00000000" + - "FFFFFFFC", 16); - private static final BigInteger P_384_B = new BigInteger("B3312FA7" + - "E23EE7E4" + "988E056B" + "E3F82D19" + "181D9C6E" + "FE814112" + - "0314088F" + "5013875A" + "C656398D" + "8A2ED19D" + "2A85C8ED" + - "D3EC2AEF", 16); - private static final BigInteger P_384_G_X = new BigInteger("AA87CA22" + - "BE8B0537" + "8EB1C71E" + "F320AD74" + "6E1D3B62" + "8BA79B98" + - "59F741E0" + "82542A38" + "5502F25D" + "BF55296C" + "3A545E38" + - "72760AB7", 16); - private static final BigInteger P_384_G_Y = new BigInteger("3617DE4A" + - "96262C6F" + "5D9E98BF" + "9292DC29" + "F8F41DBD" + "289A147C" + - "E9DA3113" + "B5F0B8C0" + "0A60B1CE" + "1D7E819D" + "7A431D7C" + - "90EA0E5F", 16); - private static final BigInteger P_384_N = new BigInteger("FFFFFFFF" + - "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + - "C7634D81" + "F4372DDF" + "581A0DB2" + "48B0A77A" + "ECEC196A" + - "CCC52973", 16); - private static final int P_384_H = 1; - // Static parameter objects derived from the above parameters - private static final ECField P_384_FIELD = new ECFieldFp(P_384_Q); - private static final EllipticCurve P_384_CURVE = - new EllipticCurve(P_384_FIELD, P_384_A, P_384_B); - private static final ECPoint P_384_G = new ECPoint(P_384_G_X, P_384_G_Y); - private static final ECParameterSpec P_384_PARAMS = - new ECParameterSpec(P_384_CURVE, P_384_G, P_384_N, P_384_H); - private final KeyParser agreementKeyParser, signatureKeyParser; - private final KeyPairGenerator agreementKeyPairGenerator; - private final KeyPairGenerator signatureKeyPairGenerator; private final SecureRandom secureRandom; + private final ECKeyPairGenerator agreementKeyPairGenerator; + private final ECKeyPairGenerator signatureKeyPairGenerator; CryptoComponentImpl() { - Security.addProvider(new BouncyCastleProvider()); - try { - KeyFactory agreementKeyFactory = KeyFactory.getInstance( - AGREEMENT_KEY_PAIR_ALGO, PROVIDER); - if(LOG.isLoggable(INFO)) { - LOG.info("Agreement KeyFactory: " - + agreementKeyFactory.getClass().getName()); - } - agreementKeyParser = new Sec1KeyParser(agreementKeyFactory, - P_384_PARAMS, P_384_Q, AGREEMENT_KEY_PAIR_BITS); - KeyFactory signatureKeyFactory = KeyFactory.getInstance( - SIGNATURE_KEY_PAIR_ALGO, PROVIDER); - if(LOG.isLoggable(INFO)) { - LOG.info("Signature KeyFactory: " - + signatureKeyFactory.getClass().getName()); - } - signatureKeyParser = new Sec1KeyParser(signatureKeyFactory, - P_384_PARAMS, P_384_Q, SIGNATURE_KEY_PAIR_BITS); - agreementKeyPairGenerator = new KeyPairGeneratorSpi.ECDH(); - agreementKeyPairGenerator.initialize(AGREEMENT_KEY_PAIR_BITS); - signatureKeyPairGenerator = new KeyPairGeneratorSpi.ECDSA(); - signatureKeyPairGenerator.initialize(SIGNATURE_KEY_PAIR_BITS); - } catch(GeneralSecurityException e) { - throw new RuntimeException(e); - } + agreementKeyParser = new Sec1KeyParser(P_384_PARAMS, P_384_Q, + AGREEMENT_KEY_PAIR_BITS); + signatureKeyParser = new Sec1KeyParser(P_384_PARAMS, P_384_Q, + SIGNATURE_KEY_PAIR_BITS); secureRandom = new SecureRandom(); + ECKeyGenerationParameters params = new ECKeyGenerationParameters( + P_384_PARAMS, secureRandom); + agreementKeyPairGenerator = new ECKeyPairGenerator(); + agreementKeyPairGenerator.init(params); + signatureKeyPairGenerator = new ECKeyPairGenerator(); + signatureKeyPairGenerator.init(params); } - public ErasableKey generateSecretKey() { + public SecretKey generateSecretKey() { byte[] b = new byte[CIPHER_KEY_BYTES]; secureRandom.nextBytes(b); - return new ErasableKeyImpl(b, CIPHER_ALGO); + return new SecretKeyImpl(b); } public MessageDigest getMessageDigest() { - return new DoubleDigest(new SHA384.Digest()); + return new DoubleDigest(new SHA384Digest()); } public PseudoRandom getPseudoRandom(int seed1, int seed2) { @@ -181,25 +113,21 @@ class CryptoComponentImpl implements CryptoComponent { } public Signature getSignature() { - try { - Signature signature = Signature.getInstance(SIGNATURE_ALGO, - PROVIDER); - if(LOG.isLoggable(INFO)) - LOG.info("Signature: " + signature.getClass().getName()); - return signature; - } catch(GeneralSecurityException e) { - throw new RuntimeException(e); - } + return new SignatureImpl(secureRandom); } public KeyPair generateAgreementKeyPair() { - KeyPair keyPair = agreementKeyPairGenerator.generateKeyPair(); - // Check that the key pair uses NIST curve P-384 - ECPublicKey publicKey = checkP384Params(keyPair.getPublic()); + AsymmetricCipherKeyPair keyPair = + agreementKeyPairGenerator.generateKeyPair(); // Return a wrapper that uses the SEC 1 encoding - publicKey = new Sec1PublicKey(publicKey, AGREEMENT_KEY_PAIR_BITS); - ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate(); - privateKey = new Sec1PrivateKey(privateKey, AGREEMENT_KEY_PAIR_BITS); + ECPublicKeyParameters ecPublicKey = + (ECPublicKeyParameters) keyPair.getPublic(); + PublicKey publicKey = new Sec1PublicKey(ecPublicKey, + AGREEMENT_KEY_PAIR_BITS); + ECPrivateKeyParameters ecPrivateKey = + (ECPrivateKeyParameters) keyPair.getPrivate(); + PrivateKey privateKey = new Sec1PrivateKey(ecPrivateKey, + AGREEMENT_KEY_PAIR_BITS); return new KeyPair(publicKey, privateKey); } @@ -208,13 +136,17 @@ class CryptoComponentImpl implements CryptoComponent { } public KeyPair generateSignatureKeyPair() { - KeyPair keyPair = signatureKeyPairGenerator.generateKeyPair(); - // Check that the key pair uses NIST curve P-384 - ECPublicKey publicKey = checkP384Params(keyPair.getPublic()); + AsymmetricCipherKeyPair keyPair = + signatureKeyPairGenerator.generateKeyPair(); // Return a wrapper that uses the SEC 1 encoding - publicKey = new Sec1PublicKey(publicKey, SIGNATURE_KEY_PAIR_BITS); - ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate(); - privateKey = new Sec1PrivateKey(privateKey, SIGNATURE_KEY_PAIR_BITS); + ECPublicKeyParameters ecPublicKey = + (ECPublicKeyParameters) keyPair.getPublic(); + PublicKey publicKey = new Sec1PublicKey(ecPublicKey, + SIGNATURE_KEY_PAIR_BITS); + ECPrivateKeyParameters ecPrivateKey = + (ECPrivateKeyParameters) keyPair.getPrivate(); + PrivateKey privateKey = new Sec1PrivateKey(ecPrivateKey, + SIGNATURE_KEY_PAIR_BITS); return new KeyPair(publicKey, privateKey); } @@ -282,13 +214,16 @@ class CryptoComponentImpl implements CryptoComponent { // Package access for testing byte[] deriveSharedSecret(PrivateKey priv, PublicKey pub) throws GeneralSecurityException { - KeyAgreement keyAgreement = KeyAgreement.getInstance(AGREEMENT_ALGO, - PROVIDER); - if(LOG.isLoggable(INFO)) - LOG.info("KeyAgreement: " + keyAgreement.getClass().getName()); - keyAgreement.init(priv); - keyAgreement.doPhase(pub, true); - return keyAgreement.generateSecret(); + if(!(priv instanceof Sec1PrivateKey)) + throw new IllegalArgumentException(); + if(!(pub instanceof Sec1PublicKey)) + throw new IllegalArgumentException(); + ECPrivateKeyParameters ecPriv = ((Sec1PrivateKey) priv).getKey(); + ECPublicKeyParameters ecPub = ((Sec1PublicKey) pub).getKey(); + ECDHCBasicAgreement agreement = new ECDHCBasicAgreement(); + agreement.init(ecPriv); + // FIXME: Should we use another format for the shared secret? + return agreement.calculateAgreement(ecPub).toByteArray(); } public byte[] deriveInitialSecret(byte[] secret, int transportIndex) { @@ -310,7 +245,7 @@ class CryptoComponentImpl implements CryptoComponent { return counterModeKdf(secret, ROTATE, period); } - public ErasableKey deriveTagKey(byte[] secret, boolean alice) { + public SecretKey deriveTagKey(byte[] secret, boolean alice) { if(secret.length != CIPHER_KEY_BYTES) throw new IllegalArgumentException(); if(Arrays.equals(secret, BLANK_SECRET)) @@ -319,7 +254,7 @@ class CryptoComponentImpl implements CryptoComponent { else return deriveKey(secret, B_TAG, 0); } - public ErasableKey deriveFrameKey(byte[] secret, long connection, + public SecretKey deriveFrameKey(byte[] secret, long connection, boolean alice, boolean initiator) { if(secret.length != CIPHER_KEY_BYTES) throw new IllegalArgumentException(); @@ -336,21 +271,21 @@ class CryptoComponentImpl implements CryptoComponent { } } - private ErasableKey deriveKey(byte[] secret, byte[] label, long context) { + private SecretKey deriveKey(byte[] secret, byte[] label, long context) { if(secret.length != CIPHER_KEY_BYTES) throw new IllegalArgumentException(); if(Arrays.equals(secret, BLANK_SECRET)) throw new IllegalArgumentException(); byte[] key = counterModeKdf(secret, label, context); - return new ErasableKeyImpl(key, CIPHER_ALGO); + return new SecretKeyImpl(key); } public AuthenticatedCipher getFrameCipher() { AEADBlockCipher cipher = new GCMBlockCipher(new AESFastEngine()); - return new AuthenticatedCipherImpl(cipher, GCM_MAC_BYTES); + return new AuthenticatedCipherImpl(cipher, MAC_BYTES); } - public void encodeTag(byte[] tag, ErasableKey tagKey, long connection) { + public void encodeTag(byte[] tag, SecretKey tagKey, long connection) { if(tag.length < TAG_LENGTH) throw new IllegalArgumentException(); if(connection < 0 || connection > MAX_32_BIT_UNSIGNED) throw new IllegalArgumentException(); @@ -367,12 +302,12 @@ class CryptoComponentImpl implements CryptoComponent { secureRandom.nextBytes(salt); // Derive the key from the password byte[] keyBytes = pbkdf2(password, salt); - ErasableKey key = new ErasableKeyImpl(keyBytes, CIPHER_ALGO); + SecretKey key = new SecretKeyImpl(keyBytes); // Generate a random IV byte[] iv = new byte[STORAGE_IV_BYTES]; secureRandom.nextBytes(iv); // The output contains the salt, IV, ciphertext and MAC - int outputLen = salt.length + iv.length + input.length + GCM_MAC_BYTES; + int outputLen = salt.length + iv.length + input.length + MAC_BYTES; byte[] output = new byte[outputLen]; System.arraycopy(salt, 0, output, 0, salt.length); System.arraycopy(iv, 0, output, salt.length, iv.length); @@ -380,7 +315,7 @@ class CryptoComponentImpl implements CryptoComponent { try { AEADBlockCipher c = new GCMBlockCipher(new AESFastEngine()); AuthenticatedCipher cipher = new AuthenticatedCipherImpl(c, - GCM_MAC_BYTES); + MAC_BYTES); cipher.init(ENCRYPT_MODE, key, iv, null); int outputOff = salt.length + iv.length; cipher.doFinal(input, 0, input.length, output, outputOff); @@ -394,7 +329,7 @@ class CryptoComponentImpl implements CryptoComponent { public byte[] decryptWithPassword(byte[] input, char[] password) { // The input contains the salt, IV, ciphertext and MAC - if(input.length < PBKDF_SALT_BYTES + STORAGE_IV_BYTES + GCM_MAC_BYTES) + if(input.length < PBKDF_SALT_BYTES + STORAGE_IV_BYTES + MAC_BYTES) return null; // Invalid byte[] salt = new byte[PBKDF_SALT_BYTES]; System.arraycopy(input, 0, salt, 0, salt.length); @@ -402,12 +337,12 @@ class CryptoComponentImpl implements CryptoComponent { System.arraycopy(input, salt.length, iv, 0, iv.length); // Derive the key from the password byte[] keyBytes = pbkdf2(password, salt); - ErasableKey key = new ErasableKeyImpl(keyBytes, CIPHER_ALGO); + SecretKey key = new SecretKeyImpl(keyBytes); // Initialise the cipher AuthenticatedCipher cipher; try { AEADBlockCipher c = new GCMBlockCipher(new AESFastEngine()); - cipher = new AuthenticatedCipherImpl(c, GCM_MAC_BYTES); + cipher = new AuthenticatedCipherImpl(c, MAC_BYTES); cipher.init(DECRYPT_MODE, key, iv, null); } catch(GeneralSecurityException e) { key.erase(); @@ -417,7 +352,7 @@ class CryptoComponentImpl implements CryptoComponent { try { int inputOff = salt.length + iv.length; int inputLen = input.length - salt.length - iv.length; - byte[] output = new byte[inputLen - GCM_MAC_BYTES]; + byte[] output = new byte[inputLen - MAC_BYTES]; cipher.doFinal(input, inputOff, inputLen, output, 0); return output; } catch(GeneralSecurityException e) { @@ -427,23 +362,6 @@ class CryptoComponentImpl implements CryptoComponent { } } - private ECPublicKey checkP384Params(PublicKey publicKey) { - if(!(publicKey instanceof ECPublicKey)) throw new RuntimeException(); - ECPublicKey ecPublicKey = (ECPublicKey) publicKey; - ECParameterSpec params = ecPublicKey.getParams(); - EllipticCurve curve = params.getCurve(); - ECField field = curve.getField(); - if(!(field instanceof ECFieldFp)) throw new RuntimeException(); - BigInteger q = ((ECFieldFp) field).getP(); - if(!q.equals(P_384_Q)) throw new RuntimeException(); - if(!curve.getA().equals(P_384_A)) throw new RuntimeException(); - if(!curve.getB().equals(P_384_B)) throw new RuntimeException(); - if(!params.getGenerator().equals(P_384_G)) throw new RuntimeException(); - if(!params.getOrder().equals(P_384_N)) throw new RuntimeException(); - if(!(params.getCofactor() == P_384_H)) throw new RuntimeException(); - return ecPublicKey; - } - // Key derivation function based on a hash function - see NIST SP 800-56A, // section 5.8 private byte[] concatenationKdf(byte[] rawSecret, byte[] label, @@ -499,8 +417,6 @@ class CryptoComponentImpl implements CryptoComponent { // Password-based key derivation function - see PKCS#5 v2.1, section 5.2 private byte[] pbkdf2(char[] password, byte[] salt) { - // This code is specific to Spongy Castle because the password-based - // KDF exposed through the JCE interface is PKCS#12 byte[] utf8 = toUtf8ByteArray(password); PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(); gen.init(utf8, salt, PBKDF_ITERATIONS); diff --git a/briar-core/src/net/sf/briar/crypto/DoubleDigest.java b/briar-core/src/net/sf/briar/crypto/DoubleDigest.java index a3039845a887484c5594a01803a3d64623a983d8..20b42865fc6bb46d1017cf370d7a832c69770049 100644 --- a/briar-core/src/net/sf/briar/crypto/DoubleDigest.java +++ b/briar-core/src/net/sf/briar/crypto/DoubleDigest.java @@ -2,6 +2,8 @@ package net.sf.briar.crypto; import net.sf.briar.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. @@ -13,20 +15,22 @@ import net.sf.briar.api.crypto.MessageDigest; */ class DoubleDigest implements MessageDigest { - private final java.security.MessageDigest delegate; + private final Digest delegate; - DoubleDigest(java.security.MessageDigest delegate) { + DoubleDigest(Digest delegate) { this.delegate = delegate; } public byte[] digest() { - byte[] digest = delegate.digest(); // h(m) - delegate.update(digest); - return delegate.digest(); // h(h(m)) + byte[] digest = new byte[delegate.getDigestSize()]; + delegate.doFinal(digest, 0); // h(m) + delegate.update(digest, 0, digest.length); + delegate.doFinal(digest, 0); // h(h(m)) + return digest; } public byte[] digest(byte[] input) { - delegate.update(input); + delegate.update(input, 0, input.length); return digest(); } @@ -38,7 +42,7 @@ class DoubleDigest implements MessageDigest { } public int getDigestLength() { - return delegate.getDigestLength(); + return delegate.getDigestSize(); } public void reset() { @@ -50,7 +54,7 @@ class DoubleDigest implements MessageDigest { } public void update(byte[] input) { - delegate.update(input); + delegate.update(input, 0, input.length); } public void update(byte[] input, int offset, int len) { diff --git a/briar-core/src/net/sf/briar/crypto/ErasableKeyImpl.java b/briar-core/src/net/sf/briar/crypto/ErasableKeyImpl.java deleted file mode 100644 index bdcd40861313fc58baabbf174376ad62e8d07846..0000000000000000000000000000000000000000 --- a/briar-core/src/net/sf/briar/crypto/ErasableKeyImpl.java +++ /dev/null @@ -1,42 +0,0 @@ -package net.sf.briar.crypto; - -import net.sf.briar.api.crypto.ErasableKey; -import net.sf.briar.util.ByteUtils; - -class ErasableKeyImpl implements ErasableKey { - - private static final long serialVersionUID = -4438380720846443120L; - - private final byte[] key; - private final String algorithm; - - private boolean erased = false; // Locking: this - - ErasableKeyImpl(byte[] key, String algorithm) { - this.key = key; - this.algorithm = algorithm; - } - - public String getAlgorithm() { - return algorithm; - } - - public synchronized byte[] getEncoded() { - if(erased) throw new IllegalStateException(); - return key; - } - - public String getFormat() { - return "RAW"; - } - - public ErasableKey copy() { - return new ErasableKeyImpl(key.clone(), algorithm); - } - - public synchronized void erase() { - if(erased) throw new IllegalStateException(); - ByteUtils.erase(key); - erased = true; - } -} diff --git a/briar-core/src/net/sf/briar/crypto/P384Constants.java b/briar-core/src/net/sf/briar/crypto/P384Constants.java new file mode 100644 index 0000000000000000000000000000000000000000..067dc6dcd2d0c69bd815ad63f4f3e48dbf45a60a --- /dev/null +++ b/briar-core/src/net/sf/briar/crypto/P384Constants.java @@ -0,0 +1,41 @@ +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 6759d7a42c6731b7c5067563e96a6432b244b414..915fcbd9cdd9c736278f9e307e17341675cc4b50 100644 --- a/briar-core/src/net/sf/briar/crypto/Sec1KeyParser.java +++ b/briar-core/src/net/sf/briar/crypto/Sec1KeyParser.java @@ -1,18 +1,17 @@ package net.sf.briar.crypto; import java.math.BigInteger; -import java.security.KeyFactory; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.security.spec.ECParameterSpec; -import java.security.spec.ECPoint; -import java.security.spec.ECPrivateKeySpec; -import java.security.spec.ECPublicKeySpec; -import java.security.spec.InvalidKeySpecException; +import java.security.GeneralSecurityException; import net.sf.briar.api.crypto.KeyParser; +import net.sf.briar.api.crypto.PrivateKey; +import net.sf.briar.api.crypto.PublicKey; + +import org.spongycastle.crypto.params.ECDomainParameters; +import org.spongycastle.crypto.params.ECPrivateKeyParameters; +import org.spongycastle.crypto.params.ECPublicKeyParameters; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; /** * A key parser that uses the encoding defined in "SEC 1: Elliptic Curve @@ -21,14 +20,11 @@ import net.sf.briar.api.crypto.KeyParser; */ class Sec1KeyParser implements KeyParser { - private final KeyFactory keyFactory; - private final ECParameterSpec params; + private final ECDomainParameters params; private final BigInteger modulus; private final int keyBits, bytesPerInt, publicKeyBytes, privateKeyBytes; - Sec1KeyParser(KeyFactory keyFactory, ECParameterSpec params, - BigInteger modulus, int keyBits) { - this.keyFactory = keyFactory; + Sec1KeyParser(ECDomainParameters params, BigInteger modulus, int keyBits) { this.params = params; this.modulus = modulus; this.keyBits = keyBits; @@ -38,43 +34,48 @@ class Sec1KeyParser implements KeyParser { } public PublicKey parsePublicKey(byte[] encodedKey) - throws InvalidKeySpecException { + throws GeneralSecurityException { if(encodedKey.length != publicKeyBytes) - throw new InvalidKeySpecException(); + throw new GeneralSecurityException(); // The first byte must be 0x04 - if(encodedKey[0] != 4) throw new InvalidKeySpecException(); + if(encodedKey[0] != 4) throw new GeneralSecurityException(); // The x co-ordinate must be >= 0 and < q byte[] xBytes = new byte[bytesPerInt]; System.arraycopy(encodedKey, 1, xBytes, 0, bytesPerInt); BigInteger x = new BigInteger(1, xBytes); // Positive signum - if(x.compareTo(modulus) >= 0) throw new InvalidKeySpecException(); + if(x.compareTo(modulus) >= 0) throw new GeneralSecurityException(); // The y co-ordinate must be >= 0 and < q byte[] yBytes = new byte[bytesPerInt]; System.arraycopy(encodedKey, bytesPerInt + 1, yBytes, 0, bytesPerInt); BigInteger y = new BigInteger(1, yBytes); // Positive signum - if(y.compareTo(modulus) >= 0) throw new InvalidKeySpecException(); + if(y.compareTo(modulus) >= 0) throw new GeneralSecurityException(); // Verify that y^2 == x^3 + ax + b (mod q) - BigInteger a = params.getCurve().getA(), b = params.getCurve().getB(); + BigInteger a = params.getCurve().getA().toBigInteger(); + BigInteger b = params.getCurve().getB().toBigInteger(); BigInteger lhs = y.multiply(y).mod(modulus); BigInteger rhs = x.multiply(x).add(a).multiply(x).add(b).mod(modulus); - if(!lhs.equals(rhs)) throw new InvalidKeySpecException(); - // FIXME: Verify that n times the point (x, y) = the point at infinity + if(!lhs.equals(rhs)) throw new GeneralSecurityException(); + // Verify that the point (x, y) times n = the point at infinity + ECFieldElement elementX = new ECFieldElement.Fp(modulus, x); + ECFieldElement elementY = new ECFieldElement.Fp(modulus, y); + ECPoint pub = new ECPoint.Fp(params.getCurve(), elementX, elementY); + if(!pub.multiply(params.getN()).isInfinity()) + throw new GeneralSecurityException(); // Construct a public key from the point (x, y) and the params - ECPoint pub = new ECPoint(x, y); - ECPublicKeySpec keySpec = new ECPublicKeySpec(pub, params); - ECPublicKey k = (ECPublicKey) keyFactory.generatePublic(keySpec); + ECPublicKeyParameters k = new ECPublicKeyParameters(pub, params); return new Sec1PublicKey(k, keyBits); } public PrivateKey parsePrivateKey(byte[] encodedKey) - throws InvalidKeySpecException { + throws GeneralSecurityException { if(encodedKey.length != privateKeyBytes) - throw new InvalidKeySpecException(); - BigInteger s = new BigInteger(1, encodedKey); // Positive signum - if(s.compareTo(params.getOrder()) >= 0) - throw new InvalidKeySpecException(); - ECPrivateKeySpec keySpec = new ECPrivateKeySpec(s, params); - ECPrivateKey k = (ECPrivateKey) keyFactory.generatePrivate(keySpec); + throw new GeneralSecurityException(); + BigInteger d = new BigInteger(1, encodedKey); // Positive signum + // Verify that the private value is < n + if(d.compareTo(params.getN()) >= 0) + throw new GeneralSecurityException(); + // Construct a private key from the private value and the params + ECPrivateKeyParameters k = new ECPrivateKeyParameters(d, params); return new Sec1PrivateKey(k, keyBits); } } diff --git a/briar-core/src/net/sf/briar/crypto/Sec1PrivateKey.java b/briar-core/src/net/sf/briar/crypto/Sec1PrivateKey.java index c590975cc64366027cdb49e64a704c2b7287bc6f..fc346e839e3dcef0dd7a5e696d50c03c8a4af5f1 100644 --- a/briar-core/src/net/sf/briar/crypto/Sec1PrivateKey.java +++ b/briar-core/src/net/sf/briar/crypto/Sec1PrivateKey.java @@ -1,57 +1,32 @@ package net.sf.briar.crypto; import java.math.BigInteger; -import java.security.interfaces.ECPrivateKey; -import java.security.spec.ECParameterSpec; -class Sec1PrivateKey implements ECPrivateKey, -org.spongycastle.jce.interfaces.ECPrivateKey { +import net.sf.briar.api.crypto.PrivateKey; - private static final long serialVersionUID = -493100835871466670L; +import org.spongycastle.crypto.params.ECPrivateKeyParameters; - private final ECPrivateKey key; +class Sec1PrivateKey implements PrivateKey { + + private final ECPrivateKeyParameters key; private final int privateKeyBytes; - Sec1PrivateKey(ECPrivateKey key, int keyBits) { - // Spongy Castle only accepts instances of its own interface, so we - // have to wrap an instance of that interface and delegate to it - if(!(key instanceof org.spongycastle.jce.interfaces.ECPrivateKey)) - throw new IllegalArgumentException(); + Sec1PrivateKey(ECPrivateKeyParameters key, int keyBits) { this.key = key; privateKeyBytes = (int) Math.ceil(keyBits / 8.0); } - public String getAlgorithm() { - return key.getAlgorithm(); - } - public byte[] getEncoded() { byte[] encodedKey = new byte[privateKeyBytes]; - BigInteger s = key.getS(); + BigInteger d = key.getD(); // Copy up to privateKeyBytes bytes into exactly privateKeyBytes bytes - byte[] sBytes = s.toByteArray(); - for(int i = 0; i < sBytes.length && i < privateKeyBytes; i++) - encodedKey[privateKeyBytes - 1 - i] = sBytes[sBytes.length - 1 - i]; + byte[] dBytes = d.toByteArray(); + for(int i = 0; i < dBytes.length && i < privateKeyBytes; i++) + encodedKey[privateKeyBytes - 1 - i] = dBytes[dBytes.length - 1 - i]; return encodedKey; } - public String getFormat() { - return "SEC1"; - } - - public ECParameterSpec getParams() { - return key.getParams(); - } - - public BigInteger getS() { - return key.getS(); - } - - public org.spongycastle.jce.spec.ECParameterSpec getParameters() { - return ((org.spongycastle.jce.interfaces.ECPrivateKey) key).getParameters(); - } - - public BigInteger getD() { - return ((org.spongycastle.jce.interfaces.ECPrivateKey) key).getD(); + ECPrivateKeyParameters getKey() { + return key; } } diff --git a/briar-core/src/net/sf/briar/crypto/Sec1PublicKey.java b/briar-core/src/net/sf/briar/crypto/Sec1PublicKey.java index e3c2e32263bc87fdd99aea75d71ba432c00c2b63..2cb9a213c8038c54b0ce373ce4b1fcf6636fa023 100644 --- a/briar-core/src/net/sf/briar/crypto/Sec1PublicKey.java +++ b/briar-core/src/net/sf/briar/crypto/Sec1PublicKey.java @@ -1,42 +1,32 @@ package net.sf.briar.crypto; import java.math.BigInteger; -import java.security.interfaces.ECPublicKey; -import java.security.spec.ECParameterSpec; -import java.security.spec.ECPoint; + +import net.sf.briar.api.crypto.PublicKey; + +import org.spongycastle.crypto.params.ECPublicKeyParameters; /** * An elliptic curve public key that uses the encoding defined in "SEC 1: * Elliptic Curve Cryptography", section 2.3 (Certicom Corporation, May 2009). * Point compression is not used. */ -class Sec1PublicKey implements ECPublicKey, -org.spongycastle.jce.interfaces.ECPublicKey { +class Sec1PublicKey implements PublicKey { - private static final long serialVersionUID = -2722797033851423987L; - - private final ECPublicKey key; + private final ECPublicKeyParameters key; private final int bytesPerInt, publicKeyBytes; - Sec1PublicKey(ECPublicKey key, int keyBits) { - // Spongy Castle only accepts instances of its own interface, so we - // have to wrap an instance of that interface and delegate to it - if(!(key instanceof org.spongycastle.jce.interfaces.ECPublicKey)) - throw new IllegalArgumentException(); + Sec1PublicKey(ECPublicKeyParameters key, int keyBits) { this.key = key; bytesPerInt = (int) Math.ceil(keyBits / 8.0); publicKeyBytes = 1 + 2 * bytesPerInt; } - public String getAlgorithm() { - return key.getAlgorithm(); - } - public byte[] getEncoded() { byte[] encodedKey = new byte[publicKeyBytes]; encodedKey[0] = 4; - BigInteger x = key.getW().getAffineX(); - BigInteger y = key.getW().getAffineY(); + BigInteger x = key.getQ().getX().toBigInteger(); + BigInteger y = key.getQ().getY().toBigInteger(); // Copy up to bytesPerInt bytes into exactly bytesPerInt bytes byte[] xBytes = x.toByteArray(); for(int i = 0; i < xBytes.length && i < bytesPerInt; i++) @@ -47,23 +37,7 @@ org.spongycastle.jce.interfaces.ECPublicKey { return encodedKey; } - public String getFormat() { - return "SEC1"; - } - - public ECParameterSpec getParams() { - return key.getParams(); - } - - public ECPoint getW() { - return key.getW(); - } - - public org.spongycastle.jce.spec.ECParameterSpec getParameters() { - return ((org.spongycastle.jce.interfaces.ECPublicKey) key).getParameters(); - } - - public org.spongycastle.math.ec.ECPoint getQ() { - return ((org.spongycastle.jce.interfaces.ECPublicKey) key).getQ(); + ECPublicKeyParameters getKey() { + return key; } } diff --git a/briar-core/src/net/sf/briar/crypto/SecretKeyImpl.java b/briar-core/src/net/sf/briar/crypto/SecretKeyImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..64bbad0634074312dfd9c31ad41eba717bdd556b --- /dev/null +++ b/briar-core/src/net/sf/briar/crypto/SecretKeyImpl.java @@ -0,0 +1,30 @@ +package net.sf.briar.crypto; + +import net.sf.briar.api.crypto.SecretKey; +import net.sf.briar.util.ByteUtils; + +class SecretKeyImpl implements SecretKey { + + private final byte[] key; + + private boolean erased = false; // Locking: this + + SecretKeyImpl(byte[] key) { + this.key = key; + } + + public synchronized byte[] getEncoded() { + if(erased) throw new IllegalStateException(); + return key; + } + + public SecretKey copy() { + return new SecretKeyImpl(key.clone()); + } + + public synchronized void erase() { + if(erased) throw new IllegalStateException(); + ByteUtils.erase(key); + erased = true; + } +} diff --git a/briar-core/src/net/sf/briar/crypto/SignatureImpl.java b/briar-core/src/net/sf/briar/crypto/SignatureImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..c9f39d42b81bc00418be2388e829dd24a1aa5fc9 --- /dev/null +++ b/briar-core/src/net/sf/briar/crypto/SignatureImpl.java @@ -0,0 +1,58 @@ +package net.sf.briar.crypto; + +import java.security.GeneralSecurityException; +import java.security.SecureRandom; + +import net.sf.briar.api.crypto.PrivateKey; +import net.sf.briar.api.crypto.PublicKey; +import net.sf.briar.api.crypto.Signature; + +import org.spongycastle.crypto.digests.SHA384Digest; +import org.spongycastle.crypto.params.ECPrivateKeyParameters; +import org.spongycastle.crypto.params.ECPublicKeyParameters; +import org.spongycastle.crypto.params.ParametersWithRandom; +import org.spongycastle.crypto.signers.DSADigestSigner; +import org.spongycastle.crypto.signers.ECDSASigner; + +class SignatureImpl implements Signature { + + private final SecureRandom secureRandom; + private final DSADigestSigner signer; + + SignatureImpl(SecureRandom secureRandom) { + this.secureRandom = secureRandom; + signer = new DSADigestSigner(new ECDSASigner(), new SHA384Digest()); + } + + public void initSign(PrivateKey k) throws GeneralSecurityException { + if(!(k instanceof Sec1PrivateKey)) throw new GeneralSecurityException(); + ECPrivateKeyParameters priv = ((Sec1PrivateKey) k).getKey(); + signer.init(true, new ParametersWithRandom(priv, secureRandom)); + } + + public void initVerify(PublicKey k) throws GeneralSecurityException { + if(!(k instanceof Sec1PublicKey)) throw new GeneralSecurityException(); + ECPublicKeyParameters pub = ((Sec1PublicKey) k).getKey(); + signer.init(false, pub); + } + + public void update(byte b) { + signer.update(b); + } + + public void update(byte[] b) { + update(b, 0, b.length); + } + + public void update(byte[] b, int off, int len) { + signer.update(b, off, len); + } + + public byte[] sign() { + return signer.generateSignature(); + } + + public boolean verify(byte[] signature) { + return signer.verifySignature(signature); + } +} diff --git a/briar-core/src/net/sf/briar/invitation/Connector.java b/briar-core/src/net/sf/briar/invitation/Connector.java index 076f77cf304b84c629c4651e018e265a725be6d5..35283c7844e54cc100bb55b092175a402fe9c08b 100644 --- a/briar-core/src/net/sf/briar/invitation/Connector.java +++ b/briar-core/src/net/sf/briar/invitation/Connector.java @@ -13,8 +13,6 @@ import static net.sf.briar.api.messaging.Rating.GOOD; import java.io.IOException; import java.security.GeneralSecurityException; -import java.security.KeyPair; -import java.security.Signature; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -36,9 +34,11 @@ import net.sf.briar.api.UniqueId; import net.sf.briar.api.clock.Clock; import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.KeyManager; +import net.sf.briar.api.crypto.KeyPair; import net.sf.briar.api.crypto.KeyParser; import net.sf.briar.api.crypto.MessageDigest; import net.sf.briar.api.crypto.PseudoRandom; +import net.sf.briar.api.crypto.Signature; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DbException; import net.sf.briar.api.db.NoSuchTransportException; diff --git a/briar-core/src/net/sf/briar/messaging/MessageFactoryImpl.java b/briar-core/src/net/sf/briar/messaging/MessageFactoryImpl.java index a04838b789014e0b8ce95ced7b497ca97af97f1d..7b2b07fdea3fb2a295434991e4d257464187a299 100644 --- a/briar-core/src/net/sf/briar/messaging/MessageFactoryImpl.java +++ b/briar-core/src/net/sf/briar/messaging/MessageFactoryImpl.java @@ -16,14 +16,14 @@ import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.security.GeneralSecurityException; -import java.security.PrivateKey; import java.security.SecureRandom; -import java.security.Signature; import net.sf.briar.api.Author; import net.sf.briar.api.clock.Clock; import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.MessageDigest; +import net.sf.briar.api.crypto.PrivateKey; +import net.sf.briar.api.crypto.Signature; import net.sf.briar.api.messaging.Group; import net.sf.briar.api.messaging.Message; import net.sf.briar.api.messaging.MessageFactory; diff --git a/briar-core/src/net/sf/briar/messaging/MessageVerifierImpl.java b/briar-core/src/net/sf/briar/messaging/MessageVerifierImpl.java index eeaece89ab7ec9d95e3c0d83eb0d2b93aa132040..85d75d8880a8015f58ddd171a8e45db10adb8004 100644 --- a/briar-core/src/net/sf/briar/messaging/MessageVerifierImpl.java +++ b/briar-core/src/net/sf/briar/messaging/MessageVerifierImpl.java @@ -1,13 +1,13 @@ package net.sf.briar.messaging; import java.security.GeneralSecurityException; -import java.security.PublicKey; -import java.security.Signature; import net.sf.briar.api.Author; import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.KeyParser; import net.sf.briar.api.crypto.MessageDigest; +import net.sf.briar.api.crypto.PublicKey; +import net.sf.briar.api.crypto.Signature; import net.sf.briar.api.messaging.Group; import net.sf.briar.api.messaging.Message; import net.sf.briar.api.messaging.MessageId; diff --git a/briar-core/src/net/sf/briar/transport/ConnectionReaderFactoryImpl.java b/briar-core/src/net/sf/briar/transport/ConnectionReaderFactoryImpl.java index ae4aefb064068e3027a800cc8ba9b4484d404514..cfd2b8246e1f4d89b77cf2cb9d0785ac21357ac4 100644 --- a/briar-core/src/net/sf/briar/transport/ConnectionReaderFactoryImpl.java +++ b/briar-core/src/net/sf/briar/transport/ConnectionReaderFactoryImpl.java @@ -3,7 +3,7 @@ package net.sf.briar.transport; import java.io.InputStream; import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.crypto.ErasableKey; +import net.sf.briar.api.crypto.SecretKey; import net.sf.briar.api.transport.ConnectionContext; import net.sf.briar.api.transport.ConnectionReader; import net.sf.briar.api.transport.ConnectionReaderFactory; @@ -26,7 +26,7 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory { long connection = ctx.getConnectionNumber(); boolean weAreAlice = ctx.getAlice(); boolean initiatorIsAlice = incoming ? !weAreAlice : weAreAlice; - ErasableKey frameKey = crypto.deriveFrameKey(secret, connection, + SecretKey frameKey = crypto.deriveFrameKey(secret, connection, initiatorIsAlice, initiator); FrameReader encryption = new IncomingEncryptionLayer(in, crypto.getFrameCipher(), frameKey, maxFrameLength); @@ -35,7 +35,7 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory { public ConnectionReader createInvitationConnectionReader(InputStream in, int maxFrameLength, byte[] secret, boolean alice) { - ErasableKey frameKey = crypto.deriveFrameKey(secret, 0, true, alice); + SecretKey frameKey = crypto.deriveFrameKey(secret, 0, true, alice); FrameReader encryption = new IncomingEncryptionLayer(in, crypto.getFrameCipher(), frameKey, maxFrameLength); return new ConnectionReaderImpl(encryption, maxFrameLength); diff --git a/briar-core/src/net/sf/briar/transport/ConnectionWriterFactoryImpl.java b/briar-core/src/net/sf/briar/transport/ConnectionWriterFactoryImpl.java index 365ada7da594a5ca888d54d24eaccfbee201a2ef..fcb1e65eb5f7c11ee609b2c2224f6ec3306f81c9 100644 --- a/briar-core/src/net/sf/briar/transport/ConnectionWriterFactoryImpl.java +++ b/briar-core/src/net/sf/briar/transport/ConnectionWriterFactoryImpl.java @@ -5,7 +5,7 @@ import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; import java.io.OutputStream; import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.crypto.ErasableKey; +import net.sf.briar.api.crypto.SecretKey; import net.sf.briar.api.transport.ConnectionContext; import net.sf.briar.api.transport.ConnectionWriter; import net.sf.briar.api.transport.ConnectionWriterFactory; @@ -28,12 +28,12 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory { long connection = ctx.getConnectionNumber(); boolean weAreAlice = ctx.getAlice(); boolean initiatorIsAlice = incoming ? !weAreAlice : weAreAlice; - ErasableKey frameKey = crypto.deriveFrameKey(secret, connection, + SecretKey frameKey = crypto.deriveFrameKey(secret, connection, initiatorIsAlice, initiator); FrameWriter encryption; if(initiator) { byte[] tag = new byte[TAG_LENGTH]; - ErasableKey tagKey = crypto.deriveTagKey(secret, initiatorIsAlice); + SecretKey tagKey = crypto.deriveTagKey(secret, initiatorIsAlice); crypto.encodeTag(tag, tagKey, connection); tagKey.erase(); encryption = new OutgoingEncryptionLayer(out, capacity, @@ -47,7 +47,7 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory { public ConnectionWriter createInvitationConnectionWriter(OutputStream out, int maxFrameLength, byte[] secret, boolean alice) { - ErasableKey frameKey = crypto.deriveFrameKey(secret, 0, true, alice); + SecretKey frameKey = crypto.deriveFrameKey(secret, 0, true, alice); FrameWriter encryption = new OutgoingEncryptionLayer(out, Long.MAX_VALUE, crypto.getFrameCipher(), frameKey, maxFrameLength); diff --git a/briar-core/src/net/sf/briar/transport/IncomingEncryptionLayer.java b/briar-core/src/net/sf/briar/transport/IncomingEncryptionLayer.java index 01dc0cb4353de8267f9b8b5ff0f314d590f82eff..34ac59b205769d747118238328569c036b2d11a5 100644 --- a/briar-core/src/net/sf/briar/transport/IncomingEncryptionLayer.java +++ b/briar-core/src/net/sf/briar/transport/IncomingEncryptionLayer.java @@ -13,13 +13,13 @@ import java.security.GeneralSecurityException; import net.sf.briar.api.FormatException; import net.sf.briar.api.crypto.AuthenticatedCipher; -import net.sf.briar.api.crypto.ErasableKey; +import net.sf.briar.api.crypto.SecretKey; class IncomingEncryptionLayer implements FrameReader { private final InputStream in; private final AuthenticatedCipher frameCipher; - private final ErasableKey frameKey; + private final SecretKey frameKey; private final byte[] iv, aad, ciphertext; private final int frameLength; @@ -27,7 +27,7 @@ class IncomingEncryptionLayer implements FrameReader { private boolean finalFrame; IncomingEncryptionLayer(InputStream in, AuthenticatedCipher frameCipher, - ErasableKey frameKey, int frameLength) { + SecretKey frameKey, int frameLength) { this.in = in; this.frameCipher = frameCipher; this.frameKey = frameKey; diff --git a/briar-core/src/net/sf/briar/transport/OutgoingEncryptionLayer.java b/briar-core/src/net/sf/briar/transport/OutgoingEncryptionLayer.java index 49203a107f9e6923bf3b5ab64996c9ce946742a6..40febbb2d088623786333351cf3be4dd718e031a 100644 --- a/briar-core/src/net/sf/briar/transport/OutgoingEncryptionLayer.java +++ b/briar-core/src/net/sf/briar/transport/OutgoingEncryptionLayer.java @@ -12,13 +12,13 @@ import java.io.OutputStream; import java.security.GeneralSecurityException; import net.sf.briar.api.crypto.AuthenticatedCipher; -import net.sf.briar.api.crypto.ErasableKey; +import net.sf.briar.api.crypto.SecretKey; class OutgoingEncryptionLayer implements FrameWriter { private final OutputStream out; private final AuthenticatedCipher frameCipher; - private final ErasableKey frameKey; + private final SecretKey frameKey; private final byte[] tag, iv, aad, ciphertext; private final int frameLength, maxPayloadLength; @@ -27,7 +27,7 @@ class OutgoingEncryptionLayer implements FrameWriter { /** Constructor for the initiator's side of a connection. */ OutgoingEncryptionLayer(OutputStream out, long capacity, - AuthenticatedCipher frameCipher, ErasableKey frameKey, + AuthenticatedCipher frameCipher, SecretKey frameKey, int frameLength, byte[] tag) { this.out = out; this.capacity = capacity; @@ -45,7 +45,7 @@ class OutgoingEncryptionLayer implements FrameWriter { /** Constructor for the responder's side of a connection. */ OutgoingEncryptionLayer(OutputStream out, long capacity, - AuthenticatedCipher frameCipher, ErasableKey frameKey, + AuthenticatedCipher frameCipher, SecretKey frameKey, int frameLength) { this.out = out; this.capacity = capacity; diff --git a/briar-core/src/net/sf/briar/transport/TransportConnectionRecogniser.java b/briar-core/src/net/sf/briar/transport/TransportConnectionRecogniser.java index 8071c8334a802504f5ec71756ed62b43de775c55..d2eff12fb151a7508d8ef710e45c3ff42a7e4760 100644 --- a/briar-core/src/net/sf/briar/transport/TransportConnectionRecogniser.java +++ b/briar-core/src/net/sf/briar/transport/TransportConnectionRecogniser.java @@ -11,7 +11,7 @@ import net.sf.briar.api.Bytes; import net.sf.briar.api.ContactId; import net.sf.briar.api.TransportId; import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.crypto.ErasableKey; +import net.sf.briar.api.crypto.SecretKey; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DbException; import net.sf.briar.api.transport.ConnectionContext; @@ -41,7 +41,7 @@ class TransportConnectionRecogniser { TagContext t = tagMap.remove(new Bytes(tag)); if(t == null) return null; // The tag was not expected // Update the connection window and the expected tags - ErasableKey key = crypto.deriveTagKey(t.secret, !t.alice); + SecretKey key = crypto.deriveTagKey(t.secret, !t.alice); for(long connection : t.window.setSeen(t.connection)) { byte[] tag1 = new byte[TAG_LENGTH]; crypto.encodeTag(tag1, key, connection); @@ -72,7 +72,7 @@ class TransportConnectionRecogniser { long centre = s.getWindowCentre(); byte[] bitmap = s.getWindowBitmap(); // Create the connection window and the expected tags - ErasableKey key = crypto.deriveTagKey(secret, !alice); + SecretKey key = crypto.deriveTagKey(secret, !alice); ConnectionWindow window = new ConnectionWindow(centre, bitmap); for(long connection : window.getUnseen()) { byte[] tag = new byte[TAG_LENGTH]; @@ -98,7 +98,7 @@ class TransportConnectionRecogniser { // Locking: this private void removeSecret(RemovalContext r) { // Remove the expected tags - ErasableKey key = crypto.deriveTagKey(r.secret, !r.alice); + SecretKey key = crypto.deriveTagKey(r.secret, !r.alice); byte[] tag = new byte[TAG_LENGTH]; for(long connection : r.window.getUnseen()) { crypto.encodeTag(tag, key, connection); diff --git a/briar-tests/.classpath b/briar-tests/.classpath index ac0eb6392c7555acd4bc18c3a2d59d42e02397a2..190edff6cbb7259d4c4ced89fe016d67622f3a17 100644 --- a/briar-tests/.classpath +++ b/briar-tests/.classpath @@ -12,7 +12,6 @@ <classpathentry combineaccessrules="false" kind="src" path="/briar-core"/> <classpathentry kind="lib" path="/briar-core/libs/commons-io-2.0.1.jar"/> <classpathentry kind="lib" path="/briar-core/libs/jnotify-0.93.jar"/> - <classpathentry kind="lib" path="/briar-core/libs/scprov-jdk15on-1.47.0.3-SNAPSHOT.jar"/> <classpathentry kind="lib" path="/briar-core/libs/jssc-0.9-briar.jar"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/briar-tests/build.xml b/briar-tests/build.xml index d634e63442c102bd80d55f77e835cb8d8fc7f555..9ea36a167b3c4674acc111a29b50433bce82129a 100644 --- a/briar-tests/build.xml +++ b/briar-tests/build.xml @@ -70,12 +70,11 @@ <jvmarg value='-Djava.library.path=../briar-core/libs'/> <test name='net.sf.briar.LockFairnessTest'/> <test name='net.sf.briar.ProtocolIntegrationTest'/> - <test name='net.sf.briar.crypto.CounterModeTest'/> - <test name='net.sf.briar.crypto.ErasableKeyTest'/> <test name='net.sf.briar.crypto.KeyAgreementTest'/> <test name='net.sf.briar.crypto.KeyDerivationTest'/> <test name='net.sf.briar.crypto.KeyEncodingAndParsingTest'/> <test name="net.sf.briar.crypto.PasswordBasedKdfTest"/> + <test name='net.sf.briar.crypto.SecretKeyImplTest'/> <test name='net.sf.briar.db.BasicH2Test'/> <test name='net.sf.briar.db.DatabaseCleanerImplTest'/> <test name='net.sf.briar.db.DatabaseComponentImplTest'/> diff --git a/briar-tests/src/net/sf/briar/ProtocolIntegrationTest.java b/briar-tests/src/net/sf/briar/ProtocolIntegrationTest.java index e535ff331ed89ab38ac321c3f1a322989a0497f7..c67b30310dcd30ee1d3c7a46765afc2ec7532322 100644 --- a/briar-tests/src/net/sf/briar/ProtocolIntegrationTest.java +++ b/briar-tests/src/net/sf/briar/ProtocolIntegrationTest.java @@ -8,7 +8,6 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; -import java.security.KeyPair; import java.util.Arrays; import java.util.BitSet; import java.util.Collection; @@ -21,6 +20,7 @@ import net.sf.briar.api.ContactId; import net.sf.briar.api.TransportId; import net.sf.briar.api.TransportProperties; import net.sf.briar.api.crypto.CryptoComponent; +import net.sf.briar.api.crypto.KeyPair; import net.sf.briar.api.messaging.Ack; import net.sf.briar.api.messaging.Group; import net.sf.briar.api.messaging.GroupFactory; diff --git a/briar-tests/src/net/sf/briar/crypto/CounterModeTest.java b/briar-tests/src/net/sf/briar/crypto/CounterModeTest.java deleted file mode 100644 index d6c16f4666a3cdb4b3848aa5ad8f8d8f485a5707..0000000000000000000000000000000000000000 --- a/briar-tests/src/net/sf/briar/crypto/CounterModeTest.java +++ /dev/null @@ -1,155 +0,0 @@ -package net.sf.briar.crypto; - -import java.security.GeneralSecurityException; -import java.security.SecureRandom; -import java.security.Security; -import java.util.HashSet; -import java.util.Set; - -import javax.crypto.Cipher; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -import net.sf.briar.BriarTestCase; -import net.sf.briar.api.Bytes; - -import org.junit.Test; -import org.spongycastle.jce.provider.BouncyCastleProvider; - -public class CounterModeTest extends BriarTestCase { - - private static final String CIPHER_ALGO = "AES"; - private static final String CIPHER_MODE = "AES/CTR/NoPadding"; - private static final String PROVIDER = "SC"; - private static final int KEY_SIZE_BYTES = 32; // AES-256 - private static final int BLOCK_SIZE_BYTES = 16; - - private final SecureRandom random; - private final byte[] keyBytes; - private final SecretKeySpec key; - - public CounterModeTest() { - Security.addProvider(new BouncyCastleProvider()); - random = new SecureRandom(); - keyBytes = new byte[KEY_SIZE_BYTES]; - random.nextBytes(keyBytes); - key = new SecretKeySpec(keyBytes, CIPHER_ALGO); - } - - @Test - public void testEveryBitOfIvIsSignificant() - throws GeneralSecurityException { - // Set each bit of the IV in turn, encrypt the same plaintext and check - // that all the resulting ciphertexts are distinct - byte[] plaintext = new byte[BLOCK_SIZE_BYTES]; - random.nextBytes(plaintext); - Set<Bytes> ciphertexts = new HashSet<Bytes>(); - for(int i = 0; i < BLOCK_SIZE_BYTES * 8; i++) { - // Set the i^th bit of the IV - byte[] ivBytes = new byte[BLOCK_SIZE_BYTES]; - ivBytes[i / 8] |= (byte) (128 >> i % 8); - IvParameterSpec iv = new IvParameterSpec(ivBytes); - // Encrypt the plaintext - Cipher cipher = Cipher.getInstance(CIPHER_MODE, PROVIDER); - cipher.init(Cipher.ENCRYPT_MODE, key, iv); - byte[] ciphertext = - new byte[cipher.getOutputSize(plaintext.length)]; - cipher.doFinal(plaintext, 0, plaintext.length, ciphertext); - ciphertexts.add(new Bytes(ciphertext)); - } - // All the ciphertexts should be distinct using Arrays.equals() - assertEquals(BLOCK_SIZE_BYTES * 8, ciphertexts.size()); - } - - @Test - public void testRepeatedIvsProduceRepeatedCiphertexts() - throws GeneralSecurityException { - // This is the inverse of the previous test, to check that the - // distinct ciphertexts were due to using distinct IVs - byte[] plaintext = new byte[BLOCK_SIZE_BYTES]; - random.nextBytes(plaintext); - byte[] ivBytes = new byte[BLOCK_SIZE_BYTES]; - random.nextBytes(ivBytes); - IvParameterSpec iv = new IvParameterSpec(ivBytes); - Set<Bytes> ciphertexts = new HashSet<Bytes>(); - for(int i = 0; i < BLOCK_SIZE_BYTES * 8; i++) { - Cipher cipher = Cipher.getInstance(CIPHER_MODE, PROVIDER); - cipher.init(Cipher.ENCRYPT_MODE, key, iv); - byte[] ciphertext = - new byte[cipher.getOutputSize(plaintext.length)]; - cipher.doFinal(plaintext, 0, plaintext.length, ciphertext); - ciphertexts.add(new Bytes(ciphertext)); - } - assertEquals(1, ciphertexts.size()); - } - - @Test - public void testLeastSignificantBitsUsedAsCounter() - throws GeneralSecurityException { - // Initialise the least significant 16 bits of the IV to zero and - // encrypt ten blocks of zeroes - byte[] plaintext = new byte[BLOCK_SIZE_BYTES * 10]; - byte[] ivBytes = new byte[BLOCK_SIZE_BYTES]; - random.nextBytes(ivBytes); - ivBytes[BLOCK_SIZE_BYTES - 2] = 0; - ivBytes[BLOCK_SIZE_BYTES - 1] = 0; - IvParameterSpec iv = new IvParameterSpec(ivBytes); - Cipher cipher = Cipher.getInstance(CIPHER_MODE, PROVIDER); - cipher.init(Cipher.ENCRYPT_MODE, key, iv); - byte[] ciphertext = new byte[cipher.getOutputSize(plaintext.length)]; - cipher.doFinal(plaintext, 0, plaintext.length, ciphertext); - // Make sure the IV array hasn't been modified - assertEquals(0, ivBytes[BLOCK_SIZE_BYTES - 2]); - assertEquals(0, ivBytes[BLOCK_SIZE_BYTES - 1]); - // Initialise the least significant 16 bits of the IV to one and - // encrypt another ten blocks of zeroes - ivBytes[BLOCK_SIZE_BYTES - 1] = 1; - iv = new IvParameterSpec(ivBytes); - cipher = Cipher.getInstance(CIPHER_MODE, PROVIDER); - cipher.init(Cipher.ENCRYPT_MODE, key, iv); - byte[] ciphertext1 = new byte[cipher.getOutputSize(plaintext.length)]; - cipher.doFinal(plaintext, 0, plaintext.length, ciphertext1); - // The last nine blocks of the first ciphertext should be identical to - // the first nine blocks of the second ciphertext - for(int i = 0; i < BLOCK_SIZE_BYTES * 9; i++) { - assertEquals(ciphertext[i + BLOCK_SIZE_BYTES], ciphertext1[i]); - } - } - - @Test - public void testCounterUsesMoreThan16Bits() - throws GeneralSecurityException { - // Initialise the least significant bits of the IV to 2^16-1 and - // encrypt ten blocks of zeroes - byte[] plaintext = new byte[BLOCK_SIZE_BYTES * 10]; - byte[] ivBytes = new byte[BLOCK_SIZE_BYTES]; - random.nextBytes(ivBytes); - ivBytes[BLOCK_SIZE_BYTES - 3] = 0; - ivBytes[BLOCK_SIZE_BYTES - 2] = (byte) 255; - ivBytes[BLOCK_SIZE_BYTES - 1] = (byte) 255; - IvParameterSpec iv = new IvParameterSpec(ivBytes); - Cipher cipher = Cipher.getInstance(CIPHER_MODE, PROVIDER); - cipher.init(Cipher.ENCRYPT_MODE, key, iv); - byte[] ciphertext = new byte[cipher.getOutputSize(plaintext.length)]; - cipher.doFinal(plaintext, 0, plaintext.length, ciphertext); - // Make sure the IV array hasn't been modified - assertEquals(0, ivBytes[BLOCK_SIZE_BYTES - 3]); - assertEquals((byte) 255, ivBytes[BLOCK_SIZE_BYTES - 2]); - assertEquals((byte) 255, ivBytes[BLOCK_SIZE_BYTES - 1]); - // Initialise the least significant bits of the IV to 2^16 and - // encrypt another ten blocks of zeroes - ivBytes[BLOCK_SIZE_BYTES - 3] = 1; - ivBytes[BLOCK_SIZE_BYTES - 2] = 0; - ivBytes[BLOCK_SIZE_BYTES - 1] = 0; - iv = new IvParameterSpec(ivBytes); - cipher = Cipher.getInstance(CIPHER_MODE, PROVIDER); - cipher.init(Cipher.ENCRYPT_MODE, key, iv); - byte[] ciphertext1 = new byte[cipher.getOutputSize(plaintext.length)]; - cipher.doFinal(plaintext, 0, plaintext.length, ciphertext1); - // The last nine blocks of the first ciphertext should be identical to - // the first nine blocks of the second ciphertext - for(int i = 0; i < BLOCK_SIZE_BYTES * 9; i++) { - assertEquals(ciphertext[i + BLOCK_SIZE_BYTES], ciphertext1[i]); - } - } -} diff --git a/briar-tests/src/net/sf/briar/crypto/ErasableKeyTest.java b/briar-tests/src/net/sf/briar/crypto/ErasableKeyTest.java deleted file mode 100644 index eb448a5505c74ff09741eb247fab91c77fb489a8..0000000000000000000000000000000000000000 --- a/briar-tests/src/net/sf/briar/crypto/ErasableKeyTest.java +++ /dev/null @@ -1,79 +0,0 @@ -package net.sf.briar.crypto; - -import static org.junit.Assert.assertArrayEquals; - -import java.util.Random; - -import javax.crypto.Cipher; -import javax.crypto.Mac; -import javax.crypto.spec.IvParameterSpec; - -import net.sf.briar.BriarTestCase; -import net.sf.briar.api.crypto.ErasableKey; - -import org.junit.Test; - -public class ErasableKeyTest extends BriarTestCase { - - private static final String CIPHER = "AES"; - private static final String CIPHER_MODE = "AES/CTR/NoPadding"; - private static final int IV_BYTES = 16; // 128 bits - private static final int KEY_BYTES = 32; // 256 bits - private static final String MAC = "HMacSHA384"; - - private final Random random = new Random(); - - @Test - public void testCopiesAreErased() { - byte[] master = new byte[KEY_BYTES]; - random.nextBytes(master); - ErasableKey k = new ErasableKeyImpl(master, CIPHER); - byte[] copy = k.getEncoded(); - assertArrayEquals(master, copy); - k.erase(); - byte[] blank = new byte[KEY_BYTES]; - assertArrayEquals(blank, master); - assertArrayEquals(blank, copy); - } - - @Test - public void testErasureDoesNotAffectCipher() throws Exception { - byte[] key = new byte[KEY_BYTES]; - random.nextBytes(key); - ErasableKey k = new ErasableKeyImpl(key, CIPHER); - Cipher c = Cipher.getInstance(CIPHER_MODE); - IvParameterSpec iv = new IvParameterSpec(new byte[IV_BYTES]); - c.init(Cipher.ENCRYPT_MODE, k, iv); - // Encrypt a blank plaintext - byte[] plaintext = new byte[123]; - byte[] ciphertext = c.doFinal(plaintext); - // Erase the key and encrypt again - erase() was called after doFinal() - k.erase(); - byte[] ciphertext1 = c.doFinal(plaintext); - // Encrypt again - this time erase() was called before doFinal() - byte[] ciphertext2 = c.doFinal(plaintext); - // The ciphertexts should match - assertArrayEquals(ciphertext, ciphertext1); - assertArrayEquals(ciphertext, ciphertext2); - } - - @Test - public void testErasureDoesNotAffectMac() throws Exception { - byte[] key = new byte[KEY_BYTES]; - random.nextBytes(key); - ErasableKey k = new ErasableKeyImpl(key, CIPHER); - Mac m = Mac.getInstance(MAC); - m.init(k); - // Authenticate a blank plaintext - byte[] plaintext = new byte[123]; - byte[] mac = m.doFinal(plaintext); - // Erase the key and authenticate again - k.erase(); - byte[] mac1 = m.doFinal(plaintext); - // Authenticate again - byte[] mac2 = m.doFinal(plaintext); - // The MACs should match - assertArrayEquals(mac, mac1); - assertArrayEquals(mac, mac2); - } -} diff --git a/briar-tests/src/net/sf/briar/crypto/KeyAgreementTest.java b/briar-tests/src/net/sf/briar/crypto/KeyAgreementTest.java index d328c35e7aea3a3c5e343a1bb148d35c350d6e35..65c7e97f424b75bdd178dde6e6719ccaa633e24a 100644 --- a/briar-tests/src/net/sf/briar/crypto/KeyAgreementTest.java +++ b/briar-tests/src/net/sf/briar/crypto/KeyAgreementTest.java @@ -2,10 +2,9 @@ package net.sf.briar.crypto; import static org.junit.Assert.assertArrayEquals; -import java.security.KeyPair; - import net.sf.briar.BriarTestCase; import net.sf.briar.api.crypto.CryptoComponent; +import net.sf.briar.api.crypto.KeyPair; import org.junit.Test; diff --git a/briar-tests/src/net/sf/briar/crypto/KeyDerivationTest.java b/briar-tests/src/net/sf/briar/crypto/KeyDerivationTest.java index f3c568cec86d8d69cf0e6d5ac0cc979d55b75d2b..44c2ffaa26d4fd9121941b948eff9f17bdde57a4 100644 --- a/briar-tests/src/net/sf/briar/crypto/KeyDerivationTest.java +++ b/briar-tests/src/net/sf/briar/crypto/KeyDerivationTest.java @@ -7,7 +7,7 @@ import java.util.Random; import net.sf.briar.BriarTestCase; import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.crypto.ErasableKey; +import net.sf.briar.api.crypto.SecretKey; import org.junit.Test; @@ -24,7 +24,7 @@ public class KeyDerivationTest extends BriarTestCase { @Test public void testKeysAreDistinct() { - List<ErasableKey> keys = new ArrayList<ErasableKey>(); + List<SecretKey> keys = new ArrayList<SecretKey>(); keys.add(crypto.deriveFrameKey(secret, 0, false, false)); keys.add(crypto.deriveFrameKey(secret, 0, false, true)); keys.add(crypto.deriveFrameKey(secret, 0, true, false)); diff --git a/briar-tests/src/net/sf/briar/crypto/KeyEncodingAndParsingTest.java b/briar-tests/src/net/sf/briar/crypto/KeyEncodingAndParsingTest.java index d327d6b83eb02f00735296d59ff38b87cb920038..9ecfed57b69e075f8d32779f17456e18ba2c17f8 100644 --- a/briar-tests/src/net/sf/briar/crypto/KeyEncodingAndParsingTest.java +++ b/briar-tests/src/net/sf/briar/crypto/KeyEncodingAndParsingTest.java @@ -2,12 +2,11 @@ package net.sf.briar.crypto; import static org.junit.Assert.assertArrayEquals; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.PublicKey; - import net.sf.briar.BriarTestCase; +import net.sf.briar.api.crypto.KeyPair; import net.sf.briar.api.crypto.KeyParser; +import net.sf.briar.api.crypto.PrivateKey; +import net.sf.briar.api.crypto.PublicKey; import org.junit.Test; diff --git a/briar-tests/src/net/sf/briar/crypto/SecretKeyImplTest.java b/briar-tests/src/net/sf/briar/crypto/SecretKeyImplTest.java new file mode 100644 index 0000000000000000000000000000000000000000..be69414b0b2d8b236ed494b1dd34d74dfea4119d --- /dev/null +++ b/briar-tests/src/net/sf/briar/crypto/SecretKeyImplTest.java @@ -0,0 +1,28 @@ +package net.sf.briar.crypto; + +import static org.junit.Assert.assertArrayEquals; + +import java.util.Random; + +import net.sf.briar.BriarTestCase; +import net.sf.briar.api.crypto.SecretKey; + +import org.junit.Test; + +public class SecretKeyImplTest extends BriarTestCase { + + private static final int KEY_BYTES = 32; // 256 bits + + @Test + public void testCopiesAreErased() { + byte[] master = new byte[KEY_BYTES]; + new Random().nextBytes(master); + SecretKey k = new SecretKeyImpl(master); + byte[] copy = k.getEncoded(); + assertArrayEquals(master, copy); + k.erase(); + byte[] blank = new byte[KEY_BYTES]; + assertArrayEquals(blank, master); + assertArrayEquals(blank, copy); + } +} diff --git a/briar-tests/src/net/sf/briar/messaging/ConstantsTest.java b/briar-tests/src/net/sf/briar/messaging/ConstantsTest.java index d7aa694f64a759d9e0c81885a8272a5f917734e9..0760579ade6c3e82006d945835cdf03f9dc100a7 100644 --- a/briar-tests/src/net/sf/briar/messaging/ConstantsTest.java +++ b/briar-tests/src/net/sf/briar/messaging/ConstantsTest.java @@ -12,9 +12,6 @@ import static net.sf.briar.api.messaging.MessagingConstants.MAX_PACKET_LENGTH; import static net.sf.briar.api.messaging.MessagingConstants.MAX_SUBSCRIPTIONS; import java.io.ByteArrayOutputStream; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.Signature; import java.util.ArrayList; import java.util.Collection; import java.util.Random; @@ -29,6 +26,9 @@ import net.sf.briar.api.TransportId; import net.sf.briar.api.TransportProperties; import net.sf.briar.api.UniqueId; import net.sf.briar.api.crypto.CryptoComponent; +import net.sf.briar.api.crypto.KeyPair; +import net.sf.briar.api.crypto.PrivateKey; +import net.sf.briar.api.crypto.Signature; import net.sf.briar.api.messaging.Ack; import net.sf.briar.api.messaging.Group; import net.sf.briar.api.messaging.GroupFactory; diff --git a/briar-tests/src/net/sf/briar/messaging/ConsumersTest.java b/briar-tests/src/net/sf/briar/messaging/ConsumersTest.java index 0432c699ddd01d4746f6e26dbc3acda7fe20a4a9..c5ea141fe7414085b39a6788afc126bf701b847f 100644 --- a/briar-tests/src/net/sf/briar/messaging/ConsumersTest.java +++ b/briar-tests/src/net/sf/briar/messaging/ConsumersTest.java @@ -64,7 +64,7 @@ public class ConsumersTest extends BriarTestCase { private final java.security.MessageDigest delegate; private TestMessageDigest() throws GeneralSecurityException { - delegate = java.security.MessageDigest.getInstance("SHA-256"); + delegate = java.security.MessageDigest.getInstance("SHA-384"); } public byte[] digest() { diff --git a/briar-tests/src/net/sf/briar/transport/IncomingEncryptionLayerTest.java b/briar-tests/src/net/sf/briar/transport/IncomingEncryptionLayerTest.java index af3edcc464c9d6a4e365c6278b854269b1d44ec1..1b4071dfd120f1b60f0734cb06f5161edac5b9a0 100644 --- a/briar-tests/src/net/sf/briar/transport/IncomingEncryptionLayerTest.java +++ b/briar-tests/src/net/sf/briar/transport/IncomingEncryptionLayerTest.java @@ -13,7 +13,7 @@ import net.sf.briar.TestLifecycleModule; import net.sf.briar.api.FormatException; import net.sf.briar.api.crypto.AuthenticatedCipher; import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.crypto.ErasableKey; +import net.sf.briar.api.crypto.SecretKey; import net.sf.briar.crypto.CryptoModule; import org.junit.Test; @@ -31,7 +31,7 @@ public class IncomingEncryptionLayerTest extends BriarTestCase { private final CryptoComponent crypto; private final AuthenticatedCipher frameCipher; - private final ErasableKey frameKey; + private final SecretKey frameKey; public IncomingEncryptionLayerTest() { Injector i = Guice.createInjector(new CryptoModule(), diff --git a/briar-tests/src/net/sf/briar/transport/KeyRotationIntegrationTest.java b/briar-tests/src/net/sf/briar/transport/KeyRotationIntegrationTest.java index b106b04778fa4dd4549d028b4a157061e2b927c1..70d664955f4859867008f42c44ec0a37d723b301 100644 --- a/briar-tests/src/net/sf/briar/transport/KeyRotationIntegrationTest.java +++ b/briar-tests/src/net/sf/briar/transport/KeyRotationIntegrationTest.java @@ -14,7 +14,7 @@ import net.sf.briar.api.TransportId; import net.sf.briar.api.clock.Clock; import net.sf.briar.api.clock.Timer; import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.crypto.ErasableKey; +import net.sf.briar.api.crypto.SecretKey; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.event.DatabaseListener; import net.sf.briar.api.transport.ConnectionContext; @@ -112,9 +112,9 @@ public class KeyRotationIntegrationTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Clock clock = context.mock(Clock.class); final Timer timer = context.mock(Timer.class); - final ErasableKey k0 = context.mock(ErasableKey.class, "k0"); - final ErasableKey k1 = context.mock(ErasableKey.class, "k1"); - final ErasableKey k2 = context.mock(ErasableKey.class, "k2"); + final SecretKey k0 = context.mock(SecretKey.class, "k0"); + final SecretKey k1 = context.mock(SecretKey.class, "k1"); + final SecretKey k2 = context.mock(SecretKey.class, "k2"); final ConnectionRecogniser connectionRecogniser = new ConnectionRecogniserImpl(crypto, db); @@ -235,9 +235,9 @@ public class KeyRotationIntegrationTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Clock clock = context.mock(Clock.class); final Timer timer = context.mock(Timer.class); - final ErasableKey k0 = context.mock(ErasableKey.class, "k0"); - final ErasableKey k1 = context.mock(ErasableKey.class, "k1"); - final ErasableKey k2 = context.mock(ErasableKey.class, "k2"); + final SecretKey k0 = context.mock(SecretKey.class, "k0"); + final SecretKey k1 = context.mock(SecretKey.class, "k1"); + final SecretKey k2 = context.mock(SecretKey.class, "k2"); final ConnectionRecogniser connectionRecogniser = new ConnectionRecogniserImpl(crypto, db); @@ -369,9 +369,9 @@ public class KeyRotationIntegrationTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Clock clock = context.mock(Clock.class); final Timer timer = context.mock(Timer.class); - final ErasableKey k0 = context.mock(ErasableKey.class, "k0"); - final ErasableKey k1 = context.mock(ErasableKey.class, "k1"); - final ErasableKey k2 = context.mock(ErasableKey.class, "k2"); + final SecretKey k0 = context.mock(SecretKey.class, "k0"); + final SecretKey k1 = context.mock(SecretKey.class, "k1"); + final SecretKey k2 = context.mock(SecretKey.class, "k2"); final ConnectionRecogniser connectionRecogniser = new ConnectionRecogniserImpl(crypto, db); @@ -514,9 +514,9 @@ public class KeyRotationIntegrationTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Clock clock = context.mock(Clock.class); final Timer timer = context.mock(Timer.class); - final ErasableKey k0 = context.mock(ErasableKey.class, "k0"); - final ErasableKey k1 = context.mock(ErasableKey.class, "k1"); - final ErasableKey k2 = context.mock(ErasableKey.class, "k2"); + final SecretKey k0 = context.mock(SecretKey.class, "k0"); + final SecretKey k1 = context.mock(SecretKey.class, "k1"); + final SecretKey k2 = context.mock(SecretKey.class, "k2"); final ConnectionRecogniser connectionRecogniser = new ConnectionRecogniserImpl(crypto, db); @@ -628,9 +628,9 @@ public class KeyRotationIntegrationTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Clock clock = context.mock(Clock.class); final Timer timer = context.mock(Timer.class); - final ErasableKey k1 = context.mock(ErasableKey.class, "k1"); - final ErasableKey k2 = context.mock(ErasableKey.class, "k2"); - final ErasableKey k3 = context.mock(ErasableKey.class, "k3"); + final SecretKey k1 = context.mock(SecretKey.class, "k1"); + final SecretKey k2 = context.mock(SecretKey.class, "k2"); + final SecretKey k3 = context.mock(SecretKey.class, "k3"); final ConnectionRecogniser connectionRecogniser = new ConnectionRecogniserImpl(crypto, db); @@ -752,9 +752,9 @@ public class KeyRotationIntegrationTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Clock clock = context.mock(Clock.class); final Timer timer = context.mock(Timer.class); - final ErasableKey k2 = context.mock(ErasableKey.class, "k2"); - final ErasableKey k3 = context.mock(ErasableKey.class, "k3"); - final ErasableKey k4 = context.mock(ErasableKey.class, "k4"); + final SecretKey k2 = context.mock(SecretKey.class, "k2"); + final SecretKey k3 = context.mock(SecretKey.class, "k3"); + final SecretKey k4 = context.mock(SecretKey.class, "k4"); final ConnectionRecogniser connectionRecogniser = new ConnectionRecogniserImpl(crypto, db); @@ -885,7 +885,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase { public Object invoke(Invocation invocation) throws Throwable { byte[] tag = (byte[]) invocation.getParameter(0); - ErasableKey key = (ErasableKey) invocation.getParameter(1); + SecretKey key = (SecretKey) invocation.getParameter(1); long connection = (Long) invocation.getParameter(2); encodeTag(tag, key.getEncoded(), connection); return null; diff --git a/briar-tests/src/net/sf/briar/transport/OutgoingEncryptionLayerTest.java b/briar-tests/src/net/sf/briar/transport/OutgoingEncryptionLayerTest.java index 648c3c0da295e17218e1575e50adff465cbb69c3..683ea2847cc369d19b47361e247408e69d0d5141 100644 --- a/briar-tests/src/net/sf/briar/transport/OutgoingEncryptionLayerTest.java +++ b/briar-tests/src/net/sf/briar/transport/OutgoingEncryptionLayerTest.java @@ -13,7 +13,7 @@ import net.sf.briar.BriarTestCase; import net.sf.briar.TestLifecycleModule; import net.sf.briar.api.crypto.AuthenticatedCipher; import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.crypto.ErasableKey; +import net.sf.briar.api.crypto.SecretKey; import net.sf.briar.crypto.CryptoModule; import org.junit.Test; @@ -47,7 +47,7 @@ public class OutgoingEncryptionLayerTest extends BriarTestCase { byte[] iv = new byte[IV_LENGTH], aad = new byte[AAD_LENGTH]; byte[] plaintext = new byte[FRAME_LENGTH - MAC_LENGTH]; byte[] ciphertext = new byte[FRAME_LENGTH]; - ErasableKey frameKey = crypto.generateSecretKey(); + SecretKey frameKey = crypto.generateSecretKey(); // Calculate the expected ciphertext FrameEncoder.encodeIv(iv, 0); FrameEncoder.encodeAad(aad, 0, plaintext.length); diff --git a/briar-tests/src/net/sf/briar/transport/TransportConnectionRecogniserTest.java b/briar-tests/src/net/sf/briar/transport/TransportConnectionRecogniserTest.java index 3f5b2225d2fc8bd47973443c0aa125d6596ac171..dd961e9b8eb4cf5549fb9f6ae1ec7870f14f299b 100644 --- a/briar-tests/src/net/sf/briar/transport/TransportConnectionRecogniserTest.java +++ b/briar-tests/src/net/sf/briar/transport/TransportConnectionRecogniserTest.java @@ -10,7 +10,7 @@ import net.sf.briar.TestUtils; import net.sf.briar.api.ContactId; import net.sf.briar.api.TransportId; import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.crypto.ErasableKey; +import net.sf.briar.api.crypto.SecretKey; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.transport.ConnectionContext; import net.sf.briar.api.transport.TemporarySecret; @@ -36,7 +36,7 @@ public class TransportConnectionRecogniserTest extends BriarTestCase { final byte[] secret = new byte[32]; new Random().nextBytes(secret); final boolean alice = false; - final ErasableKey tagKey = context.mock(ErasableKey.class); + final SecretKey tagKey = context.mock(SecretKey.class); final DatabaseComponent db = context.mock(DatabaseComponent.class); context.checking(new Expectations() {{ // Add secret @@ -74,7 +74,7 @@ public class TransportConnectionRecogniserTest extends BriarTestCase { final byte[] secret = new byte[32]; new Random().nextBytes(secret); final boolean alice = false; - final ErasableKey tagKey = context.mock(ErasableKey.class); + final SecretKey tagKey = context.mock(SecretKey.class); final DatabaseComponent db = context.mock(DatabaseComponent.class); context.checking(new Expectations() {{ // Add secret diff --git a/briar-tests/src/net/sf/briar/transport/TransportIntegrationTest.java b/briar-tests/src/net/sf/briar/transport/TransportIntegrationTest.java index dd6d5adbcf5f7c984c126c77ce27d054cdaf1169..331d224388bb215345d58ff271e5d3f531c30d31 100644 --- a/briar-tests/src/net/sf/briar/transport/TransportIntegrationTest.java +++ b/briar-tests/src/net/sf/briar/transport/TransportIntegrationTest.java @@ -18,7 +18,7 @@ import net.sf.briar.api.ContactId; import net.sf.briar.api.TransportId; import net.sf.briar.api.crypto.AuthenticatedCipher; import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.crypto.ErasableKey; +import net.sf.briar.api.crypto.SecretKey; import net.sf.briar.api.transport.ConnectionContext; import net.sf.briar.api.transport.ConnectionWriter; import net.sf.briar.api.transport.ConnectionWriterFactory; @@ -42,7 +42,7 @@ public class TransportIntegrationTest extends BriarTestCase { private final AuthenticatedCipher frameCipher; private final Random random; private final byte[] secret; - private final ErasableKey frameKey; + private final SecretKey frameKey; public TransportIntegrationTest() { Module testModule = new AbstractModule() { @@ -82,7 +82,7 @@ public class TransportIntegrationTest extends BriarTestCase { byte[] frame1 = new byte[321]; random.nextBytes(frame1); // Copy the frame key - the copy will be erased - ErasableKey frameCopy = frameKey.copy(); + SecretKey frameCopy = frameKey.copy(); // Write the frames ByteArrayOutputStream out = new ByteArrayOutputStream(); FrameWriter encryptionOut = new OutgoingEncryptionLayer(out,