Use the BouncyCastle provider so we can be sure we won't get

NoSuchAlgorithmExceptions. Key generation is *slow* - I guess that's a
good sign. ;-)
This commit is contained in:
akwizgran
2011-07-25 10:38:46 +01:00
parent c98c968b87
commit fb95565880
13 changed files with 126 additions and 78 deletions

View File

@@ -16,5 +16,6 @@
<classpathentry kind="lib" path="lib/commons-io-2.0.1.jar"/> <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/h2small-1.3.157.jar"/>
<classpathentry kind="lib" path="lib/test/junit-4.9b3.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"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

View File

@@ -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();
}

View File

@@ -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);
}
}
}

View File

@@ -1,60 +1,14 @@
package net.sf.briar.crypto; package net.sf.briar.crypto;
import java.security.KeyPair; import net.sf.briar.api.crypto.CryptoComponent;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import net.sf.briar.api.crypto.KeyParser;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Singleton;
public class CryptoModule extends AbstractModule { 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 @Override
protected void configure() { protected void configure() {
try { bind(CryptoComponent.class).to(CryptoComponentImpl.class).in(Singleton.class);
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);
}
} }
} }

View File

@@ -2,6 +2,7 @@ package net.sf.briar.crypto;
import java.security.KeyFactory; import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey; import java.security.PublicKey;
import java.security.spec.EncodedKeySpec; import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
@@ -13,8 +14,9 @@ class KeyParserImpl implements KeyParser {
private final KeyFactory keyFactory; private final KeyFactory keyFactory;
KeyParserImpl(String algorithm) throws NoSuchAlgorithmException { KeyParserImpl(String algorithm, String provider)
keyFactory = KeyFactory.getInstance(algorithm); throws NoSuchAlgorithmException, NoSuchProviderException {
keyFactory = KeyFactory.getInstance(algorithm, provider);
} }
public PublicKey parsePublicKey(byte[] encodedKey) public PublicKey parsePublicKey(byte[] encodedKey)

View File

@@ -3,6 +3,7 @@ package net.sf.briar.protocol;
import java.security.PublicKey; import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.crypto.KeyParser; import net.sf.briar.api.crypto.KeyParser;
import net.sf.briar.api.protocol.Group; import net.sf.briar.api.protocol.Group;
import net.sf.briar.api.protocol.GroupFactory; import net.sf.briar.api.protocol.GroupFactory;
@@ -15,8 +16,8 @@ class GroupFactoryImpl implements GroupFactory {
private final KeyParser keyParser; private final KeyParser keyParser;
@Inject @Inject
GroupFactoryImpl(KeyParser keyParser) { GroupFactoryImpl(CryptoComponent crypto) {
this.keyParser = keyParser; keyParser = crypto.getKeyParser();
} }
public Group createGroup(GroupId id, String name, boolean restricted, public Group createGroup(GroupId id, String name, boolean restricted,

View File

@@ -7,6 +7,7 @@ import java.security.KeyPair;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.Signature; import java.security.Signature;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.protocol.AuthorId; import net.sf.briar.api.protocol.AuthorId;
import net.sf.briar.api.protocol.GroupId; import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.Message; import net.sf.briar.api.protocol.Message;
@@ -25,10 +26,9 @@ class MessageEncoderImpl implements MessageEncoder {
private final WriterFactory writerFactory; private final WriterFactory writerFactory;
@Inject @Inject
MessageEncoderImpl(Signature signature, MessageDigest messageDigest, MessageEncoderImpl(CryptoComponent crypto, WriterFactory writerFactory) {
WriterFactory writerFactory) { signature = crypto.getSignature();
this.signature = signature; messageDigest = crypto.getMessageDigest();
this.messageDigest = messageDigest;
this.writerFactory = writerFactory; this.writerFactory = writerFactory;
} }

View File

@@ -3,6 +3,7 @@ package net.sf.briar.protocol.writers;
import java.io.OutputStream; import java.io.OutputStream;
import java.security.MessageDigest; 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.AckWriter;
import net.sf.briar.api.protocol.writers.BatchWriter; import net.sf.briar.api.protocol.writers.BatchWriter;
import net.sf.briar.api.protocol.writers.PacketWriterFactory; import net.sf.briar.api.protocol.writers.PacketWriterFactory;
@@ -18,9 +19,9 @@ class PacketWriterFactoryImpl implements PacketWriterFactory {
private final WriterFactory writerFactory; private final WriterFactory writerFactory;
@Inject @Inject
PacketWriterFactoryImpl(MessageDigest messageDigest, PacketWriterFactoryImpl(CryptoComponent crypto,
WriterFactory writerFactory) { WriterFactory writerFactory) {
this.messageDigest = messageDigest; messageDigest = crypto.getMessageDigest();
this.writerFactory = writerFactory; this.writerFactory = writerFactory;
} }

BIN
lib/bcprov-jdk15-146.jar Normal file

Binary file not shown.

View File

@@ -7,6 +7,7 @@ import java.security.MessageDigest;
import java.util.Collections; import java.util.Collections;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.protocol.Batch; import net.sf.briar.api.protocol.Batch;
import net.sf.briar.api.protocol.BatchId; import net.sf.briar.api.protocol.BatchId;
import net.sf.briar.api.protocol.Message; import net.sf.briar.api.protocol.Message;
@@ -42,7 +43,7 @@ public class BatchReaderTest extends TestCase {
new CryptoModule()); new CryptoModule());
readerFactory = i.getInstance(ReaderFactory.class); readerFactory = i.getInstance(ReaderFactory.class);
writerFactory = i.getInstance(WriterFactory.class); writerFactory = i.getInstance(WriterFactory.class);
messageDigest = i.getInstance(MessageDigest.class); messageDigest = i.getInstance(CryptoComponent.class).getMessageDigest();
context = new Mockery(); context = new Mockery();
message = context.mock(Message.class); message = context.mock(Message.class);
} }

View File

@@ -7,6 +7,7 @@ import java.util.Arrays;
import java.util.Random; import java.util.Random;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.serial.FormatException; import net.sf.briar.api.serial.FormatException;
import net.sf.briar.crypto.CryptoModule; import net.sf.briar.crypto.CryptoModule;
@@ -18,20 +19,18 @@ import com.google.inject.Injector;
public class ConsumersTest extends TestCase { public class ConsumersTest extends TestCase {
private Signature signature = null; private CryptoComponent crypto = null;
private KeyPair keyPair = null;
private MessageDigest messageDigest = null;
@Before @Before
public void setUp() { public void setUp() {
Injector i = Guice.createInjector(new CryptoModule()); Injector i = Guice.createInjector(new CryptoModule());
signature = i.getInstance(Signature.class); crypto = i.getInstance(CryptoComponent.class);
keyPair = i.getInstance(KeyPair.class);
messageDigest = i.getInstance(MessageDigest.class);
} }
@Test @Test
public void testSigningConsumer() throws Exception { public void testSigningConsumer() throws Exception {
Signature signature = crypto.getSignature();
KeyPair keyPair = crypto.generateKeyPair();
byte[] data = new byte[1234]; byte[] data = new byte[1234];
// Generate some random data and sign it // Generate some random data and sign it
new Random().nextBytes(data); new Random().nextBytes(data);
@@ -50,6 +49,7 @@ public class ConsumersTest extends TestCase {
@Test @Test
public void testDigestingConsumer() throws Exception { public void testDigestingConsumer() throws Exception {
MessageDigest messageDigest = crypto.getMessageDigest();
byte[] data = new byte[1234]; byte[] data = new byte[1234];
// Generate some random data and digest it // Generate some random data and digest it
new Random().nextBytes(data); new Random().nextBytes(data);

View File

@@ -13,6 +13,7 @@ import java.util.Iterator;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.briar.TestUtils; import net.sf.briar.TestUtils;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.crypto.KeyParser; import net.sf.briar.api.crypto.KeyParser;
import net.sf.briar.api.protocol.Ack; import net.sf.briar.api.protocol.Ack;
import net.sf.briar.api.protocol.Batch; import net.sf.briar.api.protocol.Batch;
@@ -63,6 +64,7 @@ public class FileReadWriteTest extends TestCase {
private final ReaderFactory readerFactory; private final ReaderFactory readerFactory;
private final WriterFactory writerFactory; private final WriterFactory writerFactory;
private final PacketWriterFactory packetWriterFactory; private final PacketWriterFactory packetWriterFactory;
private final CryptoComponent crypto;
private final Signature signature; private final Signature signature;
private final MessageDigest messageDigest, batchDigest; private final MessageDigest messageDigest, batchDigest;
private final KeyParser keyParser; private final KeyParser keyParser;
@@ -77,15 +79,16 @@ public class FileReadWriteTest extends TestCase {
readerFactory = i.getInstance(ReaderFactory.class); readerFactory = i.getInstance(ReaderFactory.class);
writerFactory = i.getInstance(WriterFactory.class); writerFactory = i.getInstance(WriterFactory.class);
packetWriterFactory = i.getInstance(PacketWriterFactory.class); packetWriterFactory = i.getInstance(PacketWriterFactory.class);
keyParser = i.getInstance(KeyParser.class); crypto = i.getInstance(CryptoComponent.class);
signature = i.getInstance(Signature.class); keyParser = crypto.getKeyParser();
messageDigest = i.getInstance(MessageDigest.class); signature = crypto.getSignature();
batchDigest = i.getInstance(MessageDigest.class); messageDigest = crypto.getMessageDigest();
batchDigest = crypto.getMessageDigest();
assertEquals(messageDigest.getDigestLength(), UniqueId.LENGTH); assertEquals(messageDigest.getDigestLength(), UniqueId.LENGTH);
assertEquals(batchDigest.getDigestLength(), UniqueId.LENGTH); assertEquals(batchDigest.getDigestLength(), UniqueId.LENGTH);
// Create and encode a test message // Create and encode a test message
MessageEncoder messageEncoder = i.getInstance(MessageEncoder.class); MessageEncoder messageEncoder = i.getInstance(MessageEncoder.class);
KeyPair keyPair = i.getInstance(KeyPair.class); KeyPair keyPair = crypto.generateKeyPair();
message = messageEncoder.encodeMessage(MessageId.NONE, sub, nick, message = messageEncoder.encodeMessage(MessageId.NONE, sub, nick,
keyPair, messageBody.getBytes("UTF-8")); keyPair, messageBody.getBytes("UTF-8"));
// Create a test group, then write and read it to calculate its ID // 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, ObjectReader<Batch> batchReader = new BatchReader(batchDigest,
messageReader, new BatchFactoryImpl()); messageReader, new BatchFactoryImpl());
ObjectReader<Group> groupReader = new GroupReader(batchDigest, ObjectReader<Group> groupReader = new GroupReader(batchDigest,
new GroupFactoryImpl(keyParser)); new GroupFactoryImpl(crypto));
ObjectReader<Subscriptions> subscriptionReader = ObjectReader<Subscriptions> subscriptionReader =
new SubscriptionReader(groupReader, new SubscriptionFactoryImpl()); new SubscriptionReader(groupReader, new SubscriptionFactoryImpl());
ObjectReader<Transports> transportReader = ObjectReader<Transports> transportReader =

View File

@@ -9,6 +9,7 @@ import java.util.Arrays;
import java.util.Random; import java.util.Random;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.crypto.CryptoModule; import net.sf.briar.crypto.CryptoModule;
import org.junit.Before; import org.junit.Before;
@@ -19,20 +20,19 @@ import com.google.inject.Injector;
public class SigningDigestingOutputStreamTest extends TestCase { public class SigningDigestingOutputStreamTest extends TestCase {
private Signature signature = null; private CryptoComponent crypto = null;
private KeyPair keyPair = null;
private MessageDigest messageDigest = null;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
Injector i = Guice.createInjector(new CryptoModule()); Injector i = Guice.createInjector(new CryptoModule());
signature = i.getInstance(Signature.class); crypto = i.getInstance(CryptoComponent.class);
keyPair = i.getInstance(KeyPair.class);
messageDigest = i.getInstance(MessageDigest.class);
} }
@Test @Test
public void testStopAndStart() throws Exception { public void testStopAndStart() throws Exception {
Signature signature = crypto.getSignature();
KeyPair keyPair = crypto.generateKeyPair();
MessageDigest messageDigest = crypto.getMessageDigest();
byte[] input = new byte[1024]; byte[] input = new byte[1024];
new Random().nextBytes(input); new Random().nextBytes(input);
ByteArrayOutputStream out = new ByteArrayOutputStream(input.length); ByteArrayOutputStream out = new ByteArrayOutputStream(input.length);
@@ -69,6 +69,8 @@ public class SigningDigestingOutputStreamTest extends TestCase {
@Test @Test
public void testSignatureExceptionThrowsIOException() throws Exception { public void testSignatureExceptionThrowsIOException() throws Exception {
Signature signature = crypto.getSignature();
MessageDigest messageDigest = crypto.getMessageDigest();
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
SigningDigestingOutputStream s = SigningDigestingOutputStream s =
new SigningDigestingOutputStream(out, signature, messageDigest); new SigningDigestingOutputStream(out, signature, messageDigest);