diff --git a/.classpath b/.classpath index 2f247967a057d62c42661a794154f6712ca18a5f..210b0bbcfa843271085ea0222dc8e29beb7ef4e5 100644 --- a/.classpath +++ b/.classpath @@ -16,5 +16,6 @@ <classpathentry kind="lib" path="lib/commons-io-2.0.1.jar"/> <classpathentry kind="lib" path="lib/h2small-1.3.157.jar"/> <classpathentry kind="lib" path="lib/test/junit-4.9b3.jar"/> + <classpathentry kind="lib" path="lib/bcprov-jdk15-146.jar"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/api/net/sf/briar/api/crypto/CryptoComponent.java b/api/net/sf/briar/api/crypto/CryptoComponent.java new file mode 100644 index 0000000000000000000000000000000000000000..3399127bc69b6f6582a8ef3cbaab2b9fa5eea1c9 --- /dev/null +++ b/api/net/sf/briar/api/crypto/CryptoComponent.java @@ -0,0 +1,17 @@ +package net.sf.briar.api.crypto; + +import java.security.KeyPair; +import java.security.MessageDigest; +import java.security.Signature; + + +public interface CryptoComponent { + + KeyPair generateKeyPair(); + + KeyParser getKeyParser(); + + MessageDigest getMessageDigest(); + + Signature getSignature(); +} diff --git a/components/net/sf/briar/crypto/CryptoComponentImpl.java b/components/net/sf/briar/crypto/CryptoComponentImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..ab0458e969ca345da3bac16a51b9bd25cbe302ee --- /dev/null +++ b/components/net/sf/briar/crypto/CryptoComponentImpl.java @@ -0,0 +1,66 @@ +package net.sf.briar.crypto; + +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Security; +import java.security.Signature; + +import net.sf.briar.api.crypto.CryptoComponent; +import net.sf.briar.api.crypto.KeyParser; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +public class CryptoComponentImpl implements CryptoComponent { + + private static final String PROVIDER = "BC"; + private static final String DIGEST_ALGO = "SHA-256"; + private static final String KEY_PAIR_ALGO = "RSA"; + private static final String SIGNATURE_ALGO = "SHA256withRSA"; + + private final KeyParser keyParser; + private final KeyPairGenerator keyPairGenerator; + + CryptoComponentImpl() { + Security.addProvider(new BouncyCastleProvider()); + try { + keyParser = new KeyParserImpl(KEY_PAIR_ALGO, PROVIDER); + keyPairGenerator = KeyPairGenerator.getInstance(KEY_PAIR_ALGO, + PROVIDER); + } catch(NoSuchAlgorithmException impossible) { + throw new RuntimeException(impossible); + } catch(NoSuchProviderException impossible) { + throw new RuntimeException(impossible); + } + } + + public KeyPair generateKeyPair() { + return keyPairGenerator.generateKeyPair(); + } + + public KeyParser getKeyParser() { + return keyParser; + } + + public MessageDigest getMessageDigest() { + try { + return MessageDigest.getInstance(DIGEST_ALGO, PROVIDER); + } catch(NoSuchAlgorithmException impossible) { + throw new RuntimeException(impossible); + } catch(NoSuchProviderException impossible) { + throw new RuntimeException(impossible); + } + } + + public Signature getSignature() { + try { + return Signature.getInstance(SIGNATURE_ALGO, PROVIDER); + } catch(NoSuchAlgorithmException impossible) { + throw new RuntimeException(impossible); + } catch(NoSuchProviderException impossible) { + throw new RuntimeException(impossible); + } + } +} diff --git a/components/net/sf/briar/crypto/CryptoModule.java b/components/net/sf/briar/crypto/CryptoModule.java index 93240a4839b21abcd9ee60f8464a6cca91085165..1f6546a8cb2b91e72b899814875b2098a4f6a905 100644 --- a/components/net/sf/briar/crypto/CryptoModule.java +++ b/components/net/sf/briar/crypto/CryptoModule.java @@ -1,60 +1,14 @@ package net.sf.briar.crypto; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.Signature; - -import net.sf.briar.api.crypto.KeyParser; +import net.sf.briar.api.crypto.CryptoComponent; import com.google.inject.AbstractModule; -import com.google.inject.Provides; +import com.google.inject.Singleton; public class CryptoModule extends AbstractModule { - private static final String DIGEST_ALGO = "SHA-256"; - private static final String KEY_PAIR_ALGO = "RSA"; - private static final String SIGNATURE_ALGO = "SHA256withRSA"; - @Override protected void configure() { - try { - bind(KeyParser.class).toInstance(new KeyParserImpl(KEY_PAIR_ALGO)); - } catch(NoSuchAlgorithmException e) { - // FIXME: Can modules throw? - throw new RuntimeException(e); - } - } - - @Provides - MessageDigest getMessageDigest() { - try { - return MessageDigest.getInstance(DIGEST_ALGO); - } catch(NoSuchAlgorithmException e) { - // FIXME: Providers should not throw - throw new RuntimeException(e); - } - } - - @Provides - Signature getSignature() { - try { - return Signature.getInstance(SIGNATURE_ALGO); - } catch(NoSuchAlgorithmException e) { - // FIXME: Providers should not throw - throw new RuntimeException(e); - } - } - - @Provides - KeyPair generateKeyPair() { - try { - KeyPairGenerator gen = KeyPairGenerator.getInstance(KEY_PAIR_ALGO); - return gen.generateKeyPair(); - } catch(NoSuchAlgorithmException e) { - // FIXME: Providers should not throw - throw new RuntimeException(e); - } + bind(CryptoComponent.class).to(CryptoComponentImpl.class).in(Singleton.class); } } diff --git a/components/net/sf/briar/crypto/KeyParserImpl.java b/components/net/sf/briar/crypto/KeyParserImpl.java index 13ae3ee5f97ca0d52b4c9ed0a3cab19ee47eff9b..ec875f60d498db185f79b7757806cb8802630cb1 100644 --- a/components/net/sf/briar/crypto/KeyParserImpl.java +++ b/components/net/sf/briar/crypto/KeyParserImpl.java @@ -2,6 +2,7 @@ package net.sf.briar.crypto; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; import java.security.PublicKey; import java.security.spec.EncodedKeySpec; import java.security.spec.InvalidKeySpecException; @@ -13,8 +14,9 @@ class KeyParserImpl implements KeyParser { private final KeyFactory keyFactory; - KeyParserImpl(String algorithm) throws NoSuchAlgorithmException { - keyFactory = KeyFactory.getInstance(algorithm); + KeyParserImpl(String algorithm, String provider) + throws NoSuchAlgorithmException, NoSuchProviderException { + keyFactory = KeyFactory.getInstance(algorithm, provider); } public PublicKey parsePublicKey(byte[] encodedKey) diff --git a/components/net/sf/briar/protocol/GroupFactoryImpl.java b/components/net/sf/briar/protocol/GroupFactoryImpl.java index b76028565f9307379eae4ee4dc1902d6debc2973..f704a31e3011a3202bbaa8f2a5ece02245192727 100644 --- a/components/net/sf/briar/protocol/GroupFactoryImpl.java +++ b/components/net/sf/briar/protocol/GroupFactoryImpl.java @@ -3,6 +3,7 @@ package net.sf.briar.protocol; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; +import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.KeyParser; import net.sf.briar.api.protocol.Group; import net.sf.briar.api.protocol.GroupFactory; @@ -15,8 +16,8 @@ class GroupFactoryImpl implements GroupFactory { private final KeyParser keyParser; @Inject - GroupFactoryImpl(KeyParser keyParser) { - this.keyParser = keyParser; + GroupFactoryImpl(CryptoComponent crypto) { + keyParser = crypto.getKeyParser(); } public Group createGroup(GroupId id, String name, boolean restricted, diff --git a/components/net/sf/briar/protocol/MessageEncoderImpl.java b/components/net/sf/briar/protocol/MessageEncoderImpl.java index 102f552e960dd6b44fa4c361dc53af6ace0d38b4..ef1107baee4e0471b914e8d2bc2f4c069d49f27d 100644 --- a/components/net/sf/briar/protocol/MessageEncoderImpl.java +++ b/components/net/sf/briar/protocol/MessageEncoderImpl.java @@ -7,6 +7,7 @@ import java.security.KeyPair; import java.security.MessageDigest; import java.security.Signature; +import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.protocol.AuthorId; import net.sf.briar.api.protocol.GroupId; import net.sf.briar.api.protocol.Message; @@ -25,10 +26,9 @@ class MessageEncoderImpl implements MessageEncoder { private final WriterFactory writerFactory; @Inject - MessageEncoderImpl(Signature signature, MessageDigest messageDigest, - WriterFactory writerFactory) { - this.signature = signature; - this.messageDigest = messageDigest; + MessageEncoderImpl(CryptoComponent crypto, WriterFactory writerFactory) { + signature = crypto.getSignature(); + messageDigest = crypto.getMessageDigest(); this.writerFactory = writerFactory; } diff --git a/components/net/sf/briar/protocol/writers/PacketWriterFactoryImpl.java b/components/net/sf/briar/protocol/writers/PacketWriterFactoryImpl.java index 97294daa51a1c8c4397f445a237ae5f95cb816f5..7d0959db5460ecee61f651e1ff25f90eafe9bf3b 100644 --- a/components/net/sf/briar/protocol/writers/PacketWriterFactoryImpl.java +++ b/components/net/sf/briar/protocol/writers/PacketWriterFactoryImpl.java @@ -3,6 +3,7 @@ package net.sf.briar.protocol.writers; import java.io.OutputStream; import java.security.MessageDigest; +import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.protocol.writers.AckWriter; import net.sf.briar.api.protocol.writers.BatchWriter; import net.sf.briar.api.protocol.writers.PacketWriterFactory; @@ -18,9 +19,9 @@ class PacketWriterFactoryImpl implements PacketWriterFactory { private final WriterFactory writerFactory; @Inject - PacketWriterFactoryImpl(MessageDigest messageDigest, + PacketWriterFactoryImpl(CryptoComponent crypto, WriterFactory writerFactory) { - this.messageDigest = messageDigest; + messageDigest = crypto.getMessageDigest(); this.writerFactory = writerFactory; } diff --git a/lib/bcprov-jdk15-146.jar b/lib/bcprov-jdk15-146.jar new file mode 100644 index 0000000000000000000000000000000000000000..daa0b54cc0fdc4d68bdeea96175b6c46f03daf46 Binary files /dev/null and b/lib/bcprov-jdk15-146.jar differ diff --git a/test/net/sf/briar/protocol/BatchReaderTest.java b/test/net/sf/briar/protocol/BatchReaderTest.java index 7e58b5c264f5a02f1be00bf34fda98493c5cc1c1..54bb5042cfef6d68c37165f0e31ade61e39c371e 100644 --- a/test/net/sf/briar/protocol/BatchReaderTest.java +++ b/test/net/sf/briar/protocol/BatchReaderTest.java @@ -7,6 +7,7 @@ import java.security.MessageDigest; import java.util.Collections; import junit.framework.TestCase; +import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.protocol.Batch; import net.sf.briar.api.protocol.BatchId; import net.sf.briar.api.protocol.Message; @@ -42,7 +43,7 @@ public class BatchReaderTest extends TestCase { new CryptoModule()); readerFactory = i.getInstance(ReaderFactory.class); writerFactory = i.getInstance(WriterFactory.class); - messageDigest = i.getInstance(MessageDigest.class); + messageDigest = i.getInstance(CryptoComponent.class).getMessageDigest(); context = new Mockery(); message = context.mock(Message.class); } diff --git a/test/net/sf/briar/protocol/ConsumersTest.java b/test/net/sf/briar/protocol/ConsumersTest.java index c2d16bf84f06f0dc6864b3097310c0660d3f5358..22c290830914f7b528b7bebbbf338addef31e2a8 100644 --- a/test/net/sf/briar/protocol/ConsumersTest.java +++ b/test/net/sf/briar/protocol/ConsumersTest.java @@ -7,6 +7,7 @@ import java.util.Arrays; import java.util.Random; import junit.framework.TestCase; +import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.serial.FormatException; import net.sf.briar.crypto.CryptoModule; @@ -18,20 +19,18 @@ import com.google.inject.Injector; public class ConsumersTest extends TestCase { - private Signature signature = null; - private KeyPair keyPair = null; - private MessageDigest messageDigest = null; + private CryptoComponent crypto = null; @Before public void setUp() { Injector i = Guice.createInjector(new CryptoModule()); - signature = i.getInstance(Signature.class); - keyPair = i.getInstance(KeyPair.class); - messageDigest = i.getInstance(MessageDigest.class); + crypto = i.getInstance(CryptoComponent.class); } @Test public void testSigningConsumer() throws Exception { + Signature signature = crypto.getSignature(); + KeyPair keyPair = crypto.generateKeyPair(); byte[] data = new byte[1234]; // Generate some random data and sign it new Random().nextBytes(data); @@ -50,6 +49,7 @@ public class ConsumersTest extends TestCase { @Test public void testDigestingConsumer() throws Exception { + MessageDigest messageDigest = crypto.getMessageDigest(); byte[] data = new byte[1234]; // Generate some random data and digest it new Random().nextBytes(data); diff --git a/test/net/sf/briar/protocol/FileReadWriteTest.java b/test/net/sf/briar/protocol/FileReadWriteTest.java index 27a180459dcebd8cc35382e1b9fc5e88d861931e..62ad02a7f4bb555bcf18132ed118447cc2366fab 100644 --- a/test/net/sf/briar/protocol/FileReadWriteTest.java +++ b/test/net/sf/briar/protocol/FileReadWriteTest.java @@ -13,6 +13,7 @@ import java.util.Iterator; import junit.framework.TestCase; import net.sf.briar.TestUtils; +import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.KeyParser; import net.sf.briar.api.protocol.Ack; import net.sf.briar.api.protocol.Batch; @@ -63,6 +64,7 @@ public class FileReadWriteTest extends TestCase { private final ReaderFactory readerFactory; private final WriterFactory writerFactory; private final PacketWriterFactory packetWriterFactory; + private final CryptoComponent crypto; private final Signature signature; private final MessageDigest messageDigest, batchDigest; private final KeyParser keyParser; @@ -77,15 +79,16 @@ public class FileReadWriteTest extends TestCase { readerFactory = i.getInstance(ReaderFactory.class); writerFactory = i.getInstance(WriterFactory.class); packetWriterFactory = i.getInstance(PacketWriterFactory.class); - keyParser = i.getInstance(KeyParser.class); - signature = i.getInstance(Signature.class); - messageDigest = i.getInstance(MessageDigest.class); - batchDigest = i.getInstance(MessageDigest.class); + crypto = i.getInstance(CryptoComponent.class); + keyParser = crypto.getKeyParser(); + signature = crypto.getSignature(); + messageDigest = crypto.getMessageDigest(); + batchDigest = crypto.getMessageDigest(); assertEquals(messageDigest.getDigestLength(), UniqueId.LENGTH); assertEquals(batchDigest.getDigestLength(), UniqueId.LENGTH); // Create and encode a test message MessageEncoder messageEncoder = i.getInstance(MessageEncoder.class); - KeyPair keyPair = i.getInstance(KeyPair.class); + KeyPair keyPair = crypto.generateKeyPair(); message = messageEncoder.encodeMessage(MessageId.NONE, sub, nick, keyPair, messageBody.getBytes("UTF-8")); // Create a test group, then write and read it to calculate its ID @@ -144,7 +147,7 @@ public class FileReadWriteTest extends TestCase { ObjectReader<Batch> batchReader = new BatchReader(batchDigest, messageReader, new BatchFactoryImpl()); ObjectReader<Group> groupReader = new GroupReader(batchDigest, - new GroupFactoryImpl(keyParser)); + new GroupFactoryImpl(crypto)); ObjectReader<Subscriptions> subscriptionReader = new SubscriptionReader(groupReader, new SubscriptionFactoryImpl()); ObjectReader<Transports> transportReader = diff --git a/test/net/sf/briar/protocol/SigningDigestingOutputStreamTest.java b/test/net/sf/briar/protocol/SigningDigestingOutputStreamTest.java index a82f75e982b0067ae44b4cef445ac180081af5bf..cf58b29fcb4ef1058b0b37379665253e6341fbbb 100644 --- a/test/net/sf/briar/protocol/SigningDigestingOutputStreamTest.java +++ b/test/net/sf/briar/protocol/SigningDigestingOutputStreamTest.java @@ -9,6 +9,7 @@ import java.util.Arrays; import java.util.Random; import junit.framework.TestCase; +import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.crypto.CryptoModule; import org.junit.Before; @@ -19,20 +20,19 @@ import com.google.inject.Injector; public class SigningDigestingOutputStreamTest extends TestCase { - private Signature signature = null; - private KeyPair keyPair = null; - private MessageDigest messageDigest = null; + private CryptoComponent crypto = null; @Before public void setUp() throws Exception { Injector i = Guice.createInjector(new CryptoModule()); - signature = i.getInstance(Signature.class); - keyPair = i.getInstance(KeyPair.class); - messageDigest = i.getInstance(MessageDigest.class); + crypto = i.getInstance(CryptoComponent.class); } @Test public void testStopAndStart() throws Exception { + Signature signature = crypto.getSignature(); + KeyPair keyPair = crypto.generateKeyPair(); + MessageDigest messageDigest = crypto.getMessageDigest(); byte[] input = new byte[1024]; new Random().nextBytes(input); ByteArrayOutputStream out = new ByteArrayOutputStream(input.length); @@ -69,6 +69,8 @@ public class SigningDigestingOutputStreamTest extends TestCase { @Test public void testSignatureExceptionThrowsIOException() throws Exception { + Signature signature = crypto.getSignature(); + MessageDigest messageDigest = crypto.getMessageDigest(); ByteArrayOutputStream out = new ByteArrayOutputStream(); SigningDigestingOutputStream s = new SigningDigestingOutputStream(out, signature, messageDigest);