diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSecureRandomProvider.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSecureRandomProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..502e7b982125d96ed790f6b1bfc925ff4fdf2574 --- /dev/null +++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSecureRandomProvider.java @@ -0,0 +1,89 @@ +package org.briarproject.bramble.system; + +import android.app.Application; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.content.ContentResolver; +import android.content.Context; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiManager; +import android.os.Build; +import android.os.Parcel; +import android.provider.Settings; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import java.io.DataOutputStream; +import java.io.IOException; + +import javax.annotation.concurrent.Immutable; +import javax.inject.Inject; + +import static android.content.Context.WIFI_SERVICE; +import static android.provider.Settings.Secure.ANDROID_ID; + +@Immutable +@NotNullByDefault +class AndroidSecureRandomProvider extends LinuxSecureRandomProvider { + + private static final int SEED_LENGTH = 32; + + private final Context appContext; + + @Inject + AndroidSecureRandomProvider(Application app) { + appContext = app.getApplicationContext(); + } + + @Override + protected void writeToEntropyPool(DataOutputStream out) throws IOException { + super.writeToEntropyPool(out); + out.writeInt(android.os.Process.myPid()); + out.writeInt(android.os.Process.myTid()); + out.writeInt(android.os.Process.myUid()); + if (Build.FINGERPRINT != null) out.writeUTF(Build.FINGERPRINT); + if (Build.SERIAL != null) out.writeUTF(Build.SERIAL); + ContentResolver contentResolver = appContext.getContentResolver(); + String id = Settings.Secure.getString(contentResolver, ANDROID_ID); + if (id != null) out.writeUTF(id); + Parcel parcel = Parcel.obtain(); + WifiManager wm = + (WifiManager) appContext.getSystemService(WIFI_SERVICE); + for (WifiConfiguration config : wm.getConfiguredNetworks()) + parcel.writeParcelable(config, 0); + BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter(); + if (bt != null) { + for (BluetoothDevice device : bt.getBondedDevices()) + parcel.writeParcelable(device, 0); + } + out.write(parcel.marshall()); + parcel.recycle(); + } + + @Override + protected void writeSeed() { + super.writeSeed(); + if (Build.VERSION.SDK_INT >= 16 && Build.VERSION.SDK_INT <= 18) + applyOpenSslFix(); + } + + // Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html + private void applyOpenSslFix() { + byte[] seed = new LinuxSecureRandomSpi().engineGenerateSeed( + SEED_LENGTH); + try { + // Seed the OpenSSL PRNG + Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto") + .getMethod("RAND_seed", byte[].class) + .invoke(null, seed); + // Mix the output of the Linux PRNG into the OpenSSL PRNG + int bytesRead = (Integer) Class.forName( + "org.apache.harmony.xnet.provider.jsse.NativeCrypto") + .getMethod("RAND_load_file", String.class, long.class) + .invoke(null, "/dev/urandom", 1024); + if (bytesRead != 1024) throw new IOException(); + } catch (Exception e) { + throw new SecurityException(e); + } + } +} diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSeedProvider.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSeedProvider.java deleted file mode 100644 index 52d15db5e30e1e88a43de7e705ea7d48d27bf5e4..0000000000000000000000000000000000000000 --- a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSeedProvider.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.briarproject.bramble.system; - -import android.app.Application; -import android.content.ContentResolver; -import android.content.Context; -import android.os.Build; -import android.provider.Settings; - -import org.briarproject.bramble.api.nullsafety.NotNullByDefault; - -import java.io.DataOutputStream; -import java.io.IOException; - -import javax.annotation.concurrent.Immutable; -import javax.inject.Inject; - -import static android.provider.Settings.Secure.ANDROID_ID; - -@Immutable -@NotNullByDefault -class AndroidSeedProvider extends LinuxSeedProvider { - - private final Context appContext; - - @Inject - AndroidSeedProvider(Application app) { - appContext = app.getApplicationContext(); - } - - @Override - void writeToEntropyPool(DataOutputStream out) throws IOException { - out.writeInt(android.os.Process.myPid()); - out.writeInt(android.os.Process.myTid()); - out.writeInt(android.os.Process.myUid()); - if (Build.FINGERPRINT != null) out.writeUTF(Build.FINGERPRINT); - if (Build.SERIAL != null) out.writeUTF(Build.SERIAL); - ContentResolver contentResolver = appContext.getContentResolver(); - String id = Settings.Secure.getString(contentResolver, ANDROID_ID); - if (id != null) out.writeUTF(id); - super.writeToEntropyPool(out); - } -} diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSystemModule.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSystemModule.java index e5976ff995b75858b9fda7f91413ac89c2195de2..79fbf44b5402f409e84f7f99709631f901a78fde 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSystemModule.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSystemModule.java @@ -4,7 +4,7 @@ import android.app.Application; import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.LocationUtils; -import org.briarproject.bramble.api.system.SeedProvider; +import org.briarproject.bramble.api.system.SecureRandomProvider; import javax.inject.Singleton; @@ -16,8 +16,8 @@ public class AndroidSystemModule { @Provides @Singleton - SeedProvider provideSeedProvider(Application app) { - return new AndroidSeedProvider(app); + SecureRandomProvider provideSecureRandomProvider(Application app) { + return new AndroidSecureRandomProvider(app); } @Provides diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/system/SecureRandomProvider.java b/bramble-api/src/main/java/org/briarproject/bramble/api/system/SecureRandomProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..7d821ba2cdb2c02f6bd35d72fc26f9eb050aa6f8 --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/system/SecureRandomProvider.java @@ -0,0 +1,23 @@ +package org.briarproject.bramble.api.system; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import java.security.Provider; +import java.security.SecureRandom; + +import javax.annotation.Nullable; + +/** + * Wrapper for a platform-specific secure random number generator. + */ +@NotNullByDefault +public interface SecureRandomProvider { + + /** + * Returns a {@link Provider} that provides a strong {@link SecureRandom} + * implementation, or null if the platform's default implementation should + * be used. + */ + @Nullable + Provider getProvider(); +} diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/system/SeedProvider.java b/bramble-api/src/main/java/org/briarproject/bramble/api/system/SeedProvider.java deleted file mode 100644 index 2d5c147f1612354d1b7b2df76dfb4518d6839318..0000000000000000000000000000000000000000 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/system/SeedProvider.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.briarproject.bramble.api.system; - -import org.briarproject.bramble.api.nullsafety.NotNullByDefault; - -/** - * Uses a platform-specific source to provide a seed for a pseudo-random - * number generator. - */ -@NotNullByDefault -public interface SeedProvider { - - /** - * The length of the seed in bytes. - */ - int SEED_BYTES = 32; - - byte[] getSeed(); -} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/CombinedSecureRandom.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/CombinedSecureRandom.java deleted file mode 100644 index 82c9d50d606b97602ad3dd212153532d7fc20660..0000000000000000000000000000000000000000 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/CombinedSecureRandom.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.briarproject.bramble.crypto; - -import java.security.Provider; -import java.security.SecureRandom; -import java.security.SecureRandomSpi; - -/** - * A {@link SecureRandom} implementation that combines the outputs of two or - * more other implementations using XOR. - */ -class CombinedSecureRandom extends SecureRandom { - - private static final Provider PROVIDER = new CombinedProvider(); - - CombinedSecureRandom(SecureRandom... randoms) { - super(new CombinedSecureRandomSpi(randoms), PROVIDER); - } - - private static class CombinedSecureRandomSpi extends SecureRandomSpi { - - private final SecureRandom[] randoms; - - private CombinedSecureRandomSpi(SecureRandom... randoms) { - if (randoms.length < 2) throw new IllegalArgumentException(); - this.randoms = randoms; - } - - @Override - protected byte[] engineGenerateSeed(int numBytes) { - byte[] combined = new byte[numBytes]; - for (SecureRandom random : randoms) { - byte[] b = random.generateSeed(numBytes); - int length = Math.min(numBytes, b.length); - for (int i = 0; i < length; i++) - combined[i] = (byte) (combined[i] ^ b[i]); - } - return combined; - } - - @Override - protected void engineNextBytes(byte[] b) { - byte[] temp = new byte[b.length]; - for (SecureRandom random : randoms) { - random.nextBytes(temp); - for (int i = 0; i < b.length; i++) - b[i] = (byte) (b[i] ^ temp[i]); - } - } - - @Override - protected void engineSetSeed(byte[] seed) { - for (SecureRandom random : randoms) random.setSeed(seed); - } - } - - private static class CombinedProvider extends Provider { - - private CombinedProvider() { - super("Combined", 1.0, ""); - } - } -} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoComponentImpl.java index ae25da4e189bdeb559267f07fbdac4dbbbe90140..197ef79738c379d56185f09361997554746b708f 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoComponentImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoComponentImpl.java @@ -8,7 +8,7 @@ import org.briarproject.bramble.api.crypto.PseudoRandom; import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.plugin.TransportId; -import org.briarproject.bramble.api.system.SeedProvider; +import org.briarproject.bramble.api.system.SecureRandomProvider; import org.briarproject.bramble.api.transport.IncomingKeys; import org.briarproject.bramble.api.transport.OutgoingKeys; import org.briarproject.bramble.api.transport.TransportKeys; @@ -29,7 +29,10 @@ import org.spongycastle.crypto.params.KeyParameter; import java.nio.charset.Charset; import java.security.GeneralSecurityException; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; import java.security.SecureRandom; +import java.security.Security; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -101,16 +104,26 @@ class CryptoComponentImpl implements CryptoComponent { private final MessageEncrypter messageEncrypter; @Inject - CryptoComponentImpl(SeedProvider seedProvider) { - if (!FortunaSecureRandom.selfTest()) throw new RuntimeException(); - SecureRandom platformSecureRandom = new SecureRandom(); + CryptoComponentImpl(SecureRandomProvider secureRandomProvider) { if (LOG.isLoggable(INFO)) { - String provider = platformSecureRandom.getProvider().getName(); - String algorithm = platformSecureRandom.getAlgorithm(); - LOG.info("Default SecureRandom: " + provider + " " + algorithm); + SecureRandom defaultSecureRandom = new SecureRandom(); + String name = defaultSecureRandom.getProvider().getName(); + String algorithm = defaultSecureRandom.getAlgorithm(); + LOG.info("Default SecureRandom: " + name + " " + algorithm); } - SecureRandom fortuna = new FortunaSecureRandom(seedProvider.getSeed()); - secureRandom = new CombinedSecureRandom(platformSecureRandom, fortuna); + Provider provider = secureRandomProvider.getProvider(); + if (provider == null) { + LOG.info("Using default"); + } else { + installSecureRandomProvider(provider); + if (LOG.isLoggable(INFO)) { + SecureRandom installedSecureRandom = new SecureRandom(); + String name = installedSecureRandom.getProvider().getName(); + String algorithm = installedSecureRandom.getAlgorithm(); + LOG.info("Installed SecureRandom: " + name + " " + algorithm); + } + } + secureRandom = new SecureRandom(); ECKeyGenerationParameters params = new ECKeyGenerationParameters( PARAMETERS, secureRandom); agreementKeyPairGenerator = new ECKeyPairGenerator(); @@ -124,6 +137,31 @@ class CryptoComponentImpl implements CryptoComponent { messageEncrypter = new MessageEncrypter(secureRandom); } + // Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html + private void installSecureRandomProvider(Provider provider) { + Provider[] providers = Security.getProviders("SecureRandom.SHA1PRNG"); + if (providers == null || providers.length == 0 + || !provider.getClass().equals(providers[0].getClass())) { + Security.insertProviderAt(provider, 1); + } + // Check the new provider is the default when no algorithm is specified + SecureRandom random = new SecureRandom(); + if (!provider.getClass().equals(random.getProvider().getClass())) { + throw new SecurityException("Wrong SecureRandom provider: " + + random.getProvider().getClass()); + } + // Check the new provider is the default when SHA1PRNG is specified + try { + random = SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + throw new SecurityException(e); + } + if (!provider.getClass().equals(random.getProvider().getClass())) { + throw new SecurityException("Wrong SHA1PRNG provider: " + + random.getProvider().getClass()); + } + } + @Override public SecretKey generateSecretKey() { byte[] b = new byte[SecretKey.LENGTH]; @@ -133,7 +171,10 @@ class CryptoComponentImpl implements CryptoComponent { @Override public PseudoRandom getPseudoRandom(int seed1, int seed2) { - return new PseudoRandomImpl(seed1, seed2); + byte[] seed = new byte[INT_32_BYTES * 2]; + ByteUtils.writeUint32(seed1, seed, 0); + ByteUtils.writeUint32(seed2, seed, INT_32_BYTES); + return new PseudoRandomImpl(seed); } @Override @@ -296,7 +337,7 @@ class CryptoComponentImpl implements CryptoComponent { public SecretKey deriveMasterSecret(byte[] theirPublicKey, KeyPair ourKeyPair, boolean alice) throws GeneralSecurityException { return deriveMasterSecret(deriveSharedSecret( - theirPublicKey,ourKeyPair, alice)); + theirPublicKey, ourKeyPair, alice)); } @Override @@ -607,7 +648,7 @@ class CryptoComponentImpl implements CryptoComponent { } private long sampleRunningTime(int iterations) { - byte[] password = { 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' }; + byte[] password = {'p', 'a', 's', 's', 'w', 'o', 'r', 'd'}; byte[] salt = new byte[PBKDF_SALT_BYTES]; int keyLengthInBits = SecretKey.LENGTH * 8; long start = System.nanoTime(); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoModule.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoModule.java index accfaf52791225bf4623be9125b29cf93aed21f4..6b3ea5295b9a6806dbbe7061e817d625af374109 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoModule.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoModule.java @@ -6,7 +6,7 @@ import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator; import org.briarproject.bramble.api.crypto.StreamDecrypterFactory; import org.briarproject.bramble.api.crypto.StreamEncrypterFactory; import org.briarproject.bramble.api.lifecycle.LifecycleManager; -import org.briarproject.bramble.api.system.SeedProvider; +import org.briarproject.bramble.api.system.SecureRandomProvider; import java.security.SecureRandom; import java.util.concurrent.BlockingQueue; @@ -60,8 +60,9 @@ public class CryptoModule { @Provides @Singleton - CryptoComponent provideCryptoComponent(SeedProvider seedProvider) { - return new CryptoComponentImpl(seedProvider); + CryptoComponent provideCryptoComponent( + SecureRandomProvider secureRandomProvider) { + return new CryptoComponentImpl(secureRandomProvider); } @Provides diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/DoubleDigest.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/DoubleDigest.java deleted file mode 100644 index 2bd71fa78a16fa9d5e60ef829a25d5d8ce657742..0000000000000000000000000000000000000000 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/DoubleDigest.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.briarproject.bramble.crypto; - -import org.briarproject.bramble.api.nullsafety.NotNullByDefault; -import org.spongycastle.crypto.Digest; - -import javax.annotation.concurrent.NotThreadSafe; - -/** - * A message digest that prevents length extension attacks - see Ferguson and - * Schneier, <i>Practical Cryptography</i>, chapter 6. - * <p> - * "Let h be an interative hash function. The hash function h<sub>d</sub> is - * defined by h<sub>d</sub> := h(h(m)), and has a claimed security level of - * min(k, n/2) where k is the security level of h and n is the size of the hash - * result." - */ -@NotThreadSafe -@NotNullByDefault -class DoubleDigest implements Digest { - - private final Digest delegate; - - DoubleDigest(Digest delegate) { - this.delegate = delegate; - } - - private byte[] digest() { - 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 int digest(byte[] buf, int offset, int len) { - byte[] digest = digest(); - len = Math.min(len, digest.length); - System.arraycopy(digest, 0, buf, offset, len); - return len; - } - - @Override - public int getDigestSize() { - return delegate.getDigestSize(); - } - - @Override - public String getAlgorithmName() { - return "Double " + delegate.getAlgorithmName(); - } - - @Override - public void reset() { - delegate.reset(); - } - - @Override - public void update(byte input) { - delegate.update(input); - } - - public void update(byte[] input) { - delegate.update(input, 0, input.length); - } - - @Override - public void update(byte[] input, int offset, int len) { - delegate.update(input, offset, len); - } - - @Override - public int doFinal(byte[] out, int outOff) { - return digest(out, outOff, delegate.getDigestSize()); - } - -} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/FortunaGenerator.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/FortunaGenerator.java deleted file mode 100644 index 5c36a931fdc20ee390442b74c7eba46bd36664a9..0000000000000000000000000000000000000000 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/FortunaGenerator.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.briarproject.bramble.crypto; - -import org.briarproject.bramble.api.nullsafety.NotNullByDefault; -import org.spongycastle.crypto.BlockCipher; -import org.spongycastle.crypto.digests.SHA256Digest; -import org.spongycastle.crypto.engines.AESLightEngine; -import org.spongycastle.crypto.params.KeyParameter; - -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import javax.annotation.concurrent.ThreadSafe; - -/** - * Implements the Fortuna pseudo-random number generator, as described in - * Ferguson and Schneier, <i>Practical Cryptography</i>, chapter 9. - */ -@ThreadSafe -@NotNullByDefault -class FortunaGenerator { - - private static final int MAX_BYTES_PER_REQUEST = 1024 * 1024; - private static final int KEY_BYTES = 32; - private static final int BLOCK_BYTES = 16; - - private final Lock lock = new ReentrantLock(); - - // The following are locking: lock - private final DoubleDigest digest = new DoubleDigest(new SHA256Digest()); - private final BlockCipher cipher = new AESLightEngine(); - private final byte[] key = new byte[KEY_BYTES]; - private final byte[] counter = new byte[BLOCK_BYTES]; - private final byte[] buffer = new byte[BLOCK_BYTES]; - private final byte[] newKey = new byte[KEY_BYTES]; - - FortunaGenerator(byte[] seed) { - reseed(seed); - } - - void reseed(byte[] seed) { - lock.lock(); - try { - digest.update(key); - digest.update(seed); - digest.digest(key, 0, KEY_BYTES); - incrementCounter(); - } finally { - lock.unlock(); - } - - } - - // Package access for testing - void incrementCounter() { - lock.lock(); - try { - counter[0]++; - for (int i = 0; counter[i] == 0; i++) { - if (i + 1 == BLOCK_BYTES) - throw new RuntimeException("Counter exhausted"); - counter[i + 1]++; - } - } finally { - lock.unlock(); - } - } - - // Package access for testing - byte[] getCounter() { - lock.lock(); - try { - return counter; - } finally { - lock.unlock(); - } - - } - - int nextBytes(byte[] dest, int off, int len) { - lock.lock(); - try { - // Don't write more than the maximum number of bytes in one request - if (len > MAX_BYTES_PER_REQUEST) len = MAX_BYTES_PER_REQUEST; - cipher.init(true, new KeyParameter(key)); - // Generate full blocks directly into the output buffer - int fullBlocks = len / BLOCK_BYTES; - for (int i = 0; i < fullBlocks; i++) { - cipher.processBlock(counter, 0, dest, off + i * BLOCK_BYTES); - incrementCounter(); - } - // Generate a partial block if needed - int done = fullBlocks * BLOCK_BYTES, remaining = len - done; - if (remaining >= BLOCK_BYTES) throw new AssertionError(); - if (remaining > 0) { - cipher.processBlock(counter, 0, buffer, 0); - incrementCounter(); - // Copy the partial block to the output buffer and erase our copy - System.arraycopy(buffer, 0, dest, off + done, remaining); - for (int i = 0; i < BLOCK_BYTES; i++) buffer[i] = 0; - } - // Generate a new key - for (int i = 0; i < KEY_BYTES / BLOCK_BYTES; i++) { - cipher.processBlock(counter, 0, newKey, i * BLOCK_BYTES); - incrementCounter(); - } - System.arraycopy(newKey, 0, key, 0, KEY_BYTES); - for (int i = 0; i < KEY_BYTES; i++) newKey[i] = 0; - // Return the number of bytes written - return len; - } finally { - lock.unlock(); - } - } -} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/FortunaSecureRandom.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/FortunaSecureRandom.java deleted file mode 100644 index 62e609c96b960992b73926879018fea7215858d1..0000000000000000000000000000000000000000 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/FortunaSecureRandom.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.briarproject.bramble.crypto; - -import org.briarproject.bramble.util.StringUtils; - -import java.security.Provider; -import java.security.SecureRandom; -import java.security.SecureRandomSpi; -import java.util.Arrays; - -/** - * A {@link java.security.SecureRandom SecureRandom} implementation based on a - * {@link FortunaGenerator}. - */ -class FortunaSecureRandom extends SecureRandom { - - // Package access for testing - static final byte[] SELF_TEST_VECTOR_1 = - StringUtils.fromHexString("4BD6EA599D47E3EE9DD911833C29CA22"); - static final byte[] SELF_TEST_VECTOR_2 = - StringUtils.fromHexString("10984D576E6850E505CA9F42A9BFD88A"); - static final byte[] SELF_TEST_VECTOR_3 = - StringUtils.fromHexString("1E12DA166BD86DCECDE50A8296018DE2"); - - private static final Provider PROVIDER = new FortunaProvider(); - - FortunaSecureRandom(byte[] seed) { - super(new FortunaSecureRandomSpi(seed), PROVIDER); - } - - /** - * Tests that the {@link #nextBytes(byte[])} and {@link #setSeed(byte[])} - * methods are passed through to the generator in the expected way. - */ - static boolean selfTest() { - byte[] seed = new byte[32]; - SecureRandom r = new FortunaSecureRandom(seed); - byte[] output = new byte[16]; - r.nextBytes(output); - if (!Arrays.equals(SELF_TEST_VECTOR_1, output)) return false; - r.nextBytes(output); - if (!Arrays.equals(SELF_TEST_VECTOR_2, output)) return false; - r.setSeed(seed); - r.nextBytes(output); - return Arrays.equals(SELF_TEST_VECTOR_3, output); - } - - private static class FortunaSecureRandomSpi extends SecureRandomSpi { - - private final FortunaGenerator generator; - - private FortunaSecureRandomSpi(byte[] seed) { - generator = new FortunaGenerator(seed); - } - - @Override - protected byte[] engineGenerateSeed(int numBytes) { - byte[] b = new byte[numBytes]; - engineNextBytes(b); - return b; - } - - @Override - protected void engineNextBytes(byte[] b) { - int offset = 0; - while (offset < b.length) - offset += generator.nextBytes(b, offset, b.length - offset); - } - - @Override - protected void engineSetSeed(byte[] seed) { - generator.reseed(seed); - } - } - - private static class FortunaProvider extends Provider { - - private FortunaProvider() { - super("Fortuna", 1.0, ""); - } - } -} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/PseudoRandomImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/PseudoRandomImpl.java index fb02df047129f013ae928679d25ead63f3540792..1eabb29df3ccc355a6929903342a5f734c673fb4 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/PseudoRandomImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/PseudoRandomImpl.java @@ -2,30 +2,34 @@ package org.briarproject.bramble.crypto; import org.briarproject.bramble.api.crypto.PseudoRandom; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; -import org.briarproject.bramble.util.ByteUtils; +import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.engines.Salsa20Engine; +import org.spongycastle.crypto.params.KeyParameter; +import org.spongycastle.crypto.params.ParametersWithIV; import javax.annotation.concurrent.NotThreadSafe; -import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES; - @NotThreadSafe @NotNullByDefault class PseudoRandomImpl implements PseudoRandom { - private final FortunaGenerator generator; + private final Salsa20Engine cipher = new Salsa20Engine(); - PseudoRandomImpl(int seed1, int seed2) { - byte[] seed = new byte[INT_32_BYTES * 2]; - ByteUtils.writeUint32(seed1, seed, 0); - ByteUtils.writeUint32(seed2, seed, INT_32_BYTES); - generator = new FortunaGenerator(seed); + PseudoRandomImpl(byte[] seed) { + // Hash the seed to produce a 32-byte key + byte[] key = new byte[32]; + Digest digest = new Blake2sDigest(); + digest.update(seed, 0, seed.length); + digest.doFinal(key, 0); + // Initialise the stream cipher with an all-zero nonce + byte[] nonce = new byte[8]; + cipher.init(true, new ParametersWithIV(new KeyParameter(key), nonce)); } @Override public byte[] nextBytes(int length) { - byte[] b = new byte[length]; - int offset = 0; - while (offset < length) offset += generator.nextBytes(b, offset, length); - return b; + byte[] in = new byte[length], out = new byte[length]; + cipher.processBytes(in, 0, length, out, 0); + return out; } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/system/AbstractSecureRandomProvider.java b/bramble-core/src/main/java/org/briarproject/bramble/system/AbstractSecureRandomProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..c442895a23f5d5b2f6dfee9fd3b961d593622461 --- /dev/null +++ b/bramble-core/src/main/java/org/briarproject/bramble/system/AbstractSecureRandomProvider.java @@ -0,0 +1,42 @@ +package org.briarproject.bramble.system; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.system.SecureRandomProvider; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.util.Collections; +import java.util.List; +import java.util.Map.Entry; +import java.util.Properties; + +import javax.annotation.concurrent.Immutable; + +@Immutable +@NotNullByDefault +abstract class AbstractSecureRandomProvider implements SecureRandomProvider { + + // Contribute whatever slightly unpredictable info we have to the pool + protected void writeToEntropyPool(DataOutputStream out) throws IOException { + out.writeLong(System.currentTimeMillis()); + out.writeLong(System.nanoTime()); + out.writeLong(Runtime.getRuntime().freeMemory()); + List<NetworkInterface> ifaces = + Collections.list(NetworkInterface.getNetworkInterfaces()); + for (NetworkInterface i : ifaces) { + List<InetAddress> addrs = Collections.list(i.getInetAddresses()); + for (InetAddress a : addrs) out.write(a.getAddress()); + byte[] hardware = i.getHardwareAddress(); + if (hardware != null) out.write(hardware); + } + for (Entry<String, String> e : System.getenv().entrySet()) { + out.writeUTF(e.getKey()); + out.writeUTF(e.getValue()); + } + Properties properties = System.getProperties(); + for (String key : properties.stringPropertyNames()) + out.writeUTF(properties.getProperty(key)); + } +} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/system/LinuxSecureRandomProvider.java b/bramble-core/src/main/java/org/briarproject/bramble/system/LinuxSecureRandomProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..c63c02b053a7e990ceb609936ec3d8f03bb26e8e --- /dev/null +++ b/bramble-core/src/main/java/org/briarproject/bramble/system/LinuxSecureRandomProvider.java @@ -0,0 +1,69 @@ +package org.briarproject.bramble.system; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.security.Provider; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.logging.Logger; + +import javax.annotation.concurrent.Immutable; + +import static java.util.logging.Level.WARNING; + +@Immutable +@NotNullByDefault +class LinuxSecureRandomProvider extends AbstractSecureRandomProvider { + + private static final Logger LOG = + Logger.getLogger(LinuxSecureRandomProvider.class.getName()); + + private static final File RANDOM_DEVICE = new File("/dev/urandom"); + + private final AtomicBoolean seeded = new AtomicBoolean(false); + private final File outputDevice; + + LinuxSecureRandomProvider() { + this(RANDOM_DEVICE); + } + + LinuxSecureRandomProvider(File outputDevice) { + this.outputDevice = outputDevice; + } + + @Override + public Provider getProvider() { + if (!seeded.getAndSet(true)) writeSeed(); + return new LinuxProvider(); + } + + protected void writeSeed() { + try { + DataOutputStream out = new DataOutputStream( + new FileOutputStream(outputDevice)); + writeToEntropyPool(out); + out.flush(); + out.close(); + } catch (IOException e) { + // On some devices /dev/urandom isn't writable - this isn't fatal + if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + } + } + + // Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html + private static class LinuxProvider extends Provider { + + private LinuxProvider() { + super("LinuxPRNG", 1.1, "A Linux-specific PRNG using /dev/urandom"); + // Although /dev/urandom is not a SHA-1 PRNG, some callers + // explicitly request a SHA1PRNG SecureRandom and we need to + // prevent them from getting the default implementation whose + // output may have low entropy. + put("SecureRandom.SHA1PRNG", LinuxSecureRandomSpi.class.getName()); + put("SecureRandom.SHA1PRNG ImplementedIn", "Software"); + } + } +} \ No newline at end of file diff --git a/bramble-core/src/main/java/org/briarproject/bramble/system/LinuxSecureRandomSpi.java b/bramble-core/src/main/java/org/briarproject/bramble/system/LinuxSecureRandomSpi.java new file mode 100644 index 0000000000000000000000000000000000000000..6b4790ada1bf520a1214d2f4c535d49bc0bef298 --- /dev/null +++ b/bramble-core/src/main/java/org/briarproject/bramble/system/LinuxSecureRandomSpi.java @@ -0,0 +1,64 @@ +package org.briarproject.bramble.system; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.security.SecureRandomSpi; +import java.util.logging.Logger; + +import static java.util.logging.Level.WARNING; + +public class LinuxSecureRandomSpi extends SecureRandomSpi { + + private static final Logger LOG = + Logger.getLogger(LinuxSecureRandomSpi.class.getName()); + + private static final File RANDOM_DEVICE = new File("/dev/urandom"); + + private final File inputDevice, outputDevice; + + public LinuxSecureRandomSpi() { + this(RANDOM_DEVICE, RANDOM_DEVICE); + } + + LinuxSecureRandomSpi(File inputDevice, File outputDevice) { + this.inputDevice = inputDevice; + this.outputDevice = outputDevice; + } + + @Override + protected void engineSetSeed(byte[] seed) { + try { + DataOutputStream out = new DataOutputStream( + new FileOutputStream(outputDevice)); + out.write(seed); + out.flush(); + out.close(); + } catch (IOException e) { + // On some devices /dev/urandom isn't writable - this isn't fatal + if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + } + } + + @Override + protected void engineNextBytes(byte[] bytes) { + try { + DataInputStream in = new DataInputStream( + new FileInputStream(inputDevice)); + in.readFully(bytes); + in.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + protected byte[] engineGenerateSeed(int len) { + byte[] seed = new byte[len]; + engineNextBytes(seed); + return seed; + } +} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/system/LinuxSeedProvider.java b/bramble-core/src/main/java/org/briarproject/bramble/system/LinuxSeedProvider.java deleted file mode 100644 index e4141a4179acd94861cf0f6354b4b91430895db2..0000000000000000000000000000000000000000 --- a/bramble-core/src/main/java/org/briarproject/bramble/system/LinuxSeedProvider.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.briarproject.bramble.system; - -import org.briarproject.bramble.api.nullsafety.NotNullByDefault; -import org.briarproject.bramble.api.system.SeedProvider; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.util.Collections; -import java.util.List; -import java.util.logging.Logger; - -import javax.annotation.concurrent.Immutable; - -import static java.util.logging.Level.WARNING; - -@Immutable -@NotNullByDefault -class LinuxSeedProvider implements SeedProvider { - - private static final Logger LOG = - Logger.getLogger(LinuxSeedProvider.class.getName()); - - private final String outputFile, inputFile; - - LinuxSeedProvider() { - this("/dev/urandom", "/dev/urandom"); - } - - LinuxSeedProvider(String outputFile, String inputFile) { - this.outputFile = outputFile; - this.inputFile = inputFile; - } - - @Override - public byte[] getSeed() { - byte[] seed = new byte[SEED_BYTES]; - // Contribute whatever slightly unpredictable info we have to the pool - try { - DataOutputStream out = new DataOutputStream( - new FileOutputStream(outputFile)); - writeToEntropyPool(out); - out.flush(); - out.close(); - } catch (IOException e) { - // On some devices /dev/urandom isn't writable - this isn't fatal - if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); - } - // Read the seed from the pool - try { - DataInputStream in = new DataInputStream( - new FileInputStream(inputFile)); - in.readFully(seed); - in.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - return seed; - } - - void writeToEntropyPool(DataOutputStream out) throws IOException { - out.writeLong(System.currentTimeMillis()); - out.writeLong(System.nanoTime()); - List<NetworkInterface> ifaces = - Collections.list(NetworkInterface.getNetworkInterfaces()); - for (NetworkInterface i : ifaces) { - List<InetAddress> addrs = Collections.list(i.getInetAddresses()); - for (InetAddress a : addrs) out.write(a.getAddress()); - } - } -} diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/EllipticCurveMultiplicationTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/EllipticCurveMultiplicationTest.java index ce3d03e443339a041454947603ff54509d2c24d4..9be3dc0ddc5b6b8b671759800e67a94d99d4fde9 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/EllipticCurveMultiplicationTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/EllipticCurveMultiplicationTest.java @@ -45,7 +45,7 @@ public class EllipticCurveMultiplicationTest extends BrambleTestCase { byte[] seed = new byte[32]; new SecureRandom().nextBytes(seed); // Montgomery ladder multiplier - SecureRandom random = new FortunaSecureRandom(seed); + SecureRandom random = new PseudoSecureRandom(seed); ECKeyGenerationParameters montgomeryGeneratorParams = new ECKeyGenerationParameters(PARAMETERS, random); ECKeyPairGenerator montgomeryGenerator = new ECKeyPairGenerator(); @@ -63,7 +63,7 @@ public class EllipticCurveMultiplicationTest extends BrambleTestCase { ECPublicKeyParameters montgomeryPublic2 = (ECPublicKeyParameters) montgomeryKeyPair2.getPublic(); // Default multiplier - random = new FortunaSecureRandom(seed); + random = new PseudoSecureRandom(seed); ECKeyGenerationParameters defaultGeneratorParams = new ECKeyGenerationParameters(defaultParameters, random); ECKeyPairGenerator defaultGenerator = new ECKeyPairGenerator(); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/FortunaGeneratorTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/FortunaGeneratorTest.java deleted file mode 100644 index c1573f610f3fb8cfcf74e77840e511cfaea3d7e9..0000000000000000000000000000000000000000 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/FortunaGeneratorTest.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.briarproject.bramble.crypto; - -import org.briarproject.bramble.test.BrambleTestCase; -import org.junit.Test; -import org.spongycastle.crypto.BlockCipher; -import org.spongycastle.crypto.engines.AESLightEngine; -import org.spongycastle.crypto.params.KeyParameter; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -public class FortunaGeneratorTest extends BrambleTestCase { - - @Test - public void testCounterInitialisedToOne() { - FortunaGenerator f = new FortunaGenerator(new byte[32]); - // The counter is little-endian - byte[] expected = new byte[16]; - expected[0] = 1; - assertArrayEquals(expected, f.getCounter()); - } - - @Test - public void testIncrementCounter() { - FortunaGenerator f = new FortunaGenerator(new byte[32]); - // Increment the counter until it reaches 255 - for (int i = 1; i < 255; i++) f.incrementCounter(); - byte[] expected = new byte[16]; - expected[0] = (byte) 255; - assertArrayEquals(expected, f.getCounter()); - // Increment the counter again - it should carry into the next byte - f.incrementCounter(); - expected[0] = 0; - expected[1] = 1; - assertArrayEquals(expected, f.getCounter()); - // Increment the counter until it carries into the next byte - for (int i = 256; i < 65536; i++) f.incrementCounter(); - expected[0] = 0; - expected[1] = 0; - expected[2] = 1; - assertArrayEquals(expected, f.getCounter()); - } - - @Test - public void testNextBytes() { - // Generate several outputs with the same seed - they should all match - byte[] seed = new byte[32]; - byte[] out1 = new byte[48]; - new FortunaGenerator(seed).nextBytes(out1, 0, 48); - // One byte longer than a block, with an offset of one - byte[] out2 = new byte[49]; - new FortunaGenerator(seed).nextBytes(out2, 1, 48); - for (int i = 0; i < 48; i++) assertEquals(out1[i], out2[i + 1]); - // One byte shorter than a block - byte[] out3 = new byte[47]; - new FortunaGenerator(seed).nextBytes(out3, 0, 47); - for (int i = 0; i < 47; i++) assertEquals(out1[i], out3[i]); - // Less than a block, with an offset greater than a block - byte[] out4 = new byte[32]; - new FortunaGenerator(seed).nextBytes(out4, 17, 15); - for (int i = 0; i < 15; i++) assertEquals(out1[i], out4[i + 17]); - } - - @Test - public void testRekeying() { - byte[] seed = new byte[32]; - FortunaGenerator f = new FortunaGenerator(seed); - // Generate three blocks of output - byte[] out1 = new byte[48]; - f.nextBytes(out1, 0, 48); - // Create another generator with the same seed and generate one block - f = new FortunaGenerator(seed); - byte[] out2 = new byte[16]; - f.nextBytes(out2, 0, 16); - // The generator should have rekeyed with the 2nd and 3rd blocks - byte[] expectedKey = new byte[32]; - System.arraycopy(out1, 16, expectedKey, 0, 32); - // The generator's counter should have been incremented 3 times - byte[] expectedCounter = new byte[16]; - expectedCounter[0] = 4; - // The next expected output block is the counter encrypted with the key - byte[] expectedOutput = new byte[16]; - BlockCipher c = new AESLightEngine(); - c.init(true, new KeyParameter(expectedKey)); - c.processBlock(expectedCounter, 0, expectedOutput, 0); - // Check that the generator produces the expected output block - byte[] out3 = new byte[16]; - f.nextBytes(out3, 0, 16); - assertArrayEquals(expectedOutput, out3); - } - - @Test - public void testMaximumRequestLength() { - int expectedMax = 1024 * 1024; - byte[] output = new byte[expectedMax + 123]; - FortunaGenerator f = new FortunaGenerator(new byte[32]); - assertEquals(expectedMax, f.nextBytes(output, 0, output.length)); - } -} diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/FortunaSecureRandomTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/FortunaSecureRandomTest.java deleted file mode 100644 index d685ce11fba2cf0f0da06b1681727af3c65c5ca3..0000000000000000000000000000000000000000 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/FortunaSecureRandomTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.briarproject.bramble.crypto; - -import org.briarproject.bramble.test.BrambleTestCase; -import org.junit.Test; -import org.spongycastle.crypto.BlockCipher; -import org.spongycastle.crypto.digests.SHA256Digest; -import org.spongycastle.crypto.engines.AESLightEngine; -import org.spongycastle.crypto.params.KeyParameter; - -import static org.briarproject.bramble.crypto.FortunaSecureRandom.SELF_TEST_VECTOR_1; -import static org.briarproject.bramble.crypto.FortunaSecureRandom.SELF_TEST_VECTOR_2; -import static org.briarproject.bramble.crypto.FortunaSecureRandom.SELF_TEST_VECTOR_3; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertTrue; - -public class FortunaSecureRandomTest extends BrambleTestCase { - - @Test - public void testClassPassesSelfTest() { - assertTrue(FortunaSecureRandom.selfTest()); - } - - @Test - public void testSelfTestVectorsAreReproducible() { - byte[] key = new byte[32], seed = new byte[32]; - byte[] counter = new byte[16], output = new byte[16]; - byte[] newKey = new byte[32]; - // Calculate the initial key - DoubleDigest digest = new DoubleDigest(new SHA256Digest()); - digest.update(key); - digest.update(seed); - digest.digest(key, 0, 32); - // Calculate the first output block and the new key - BlockCipher c = new AESLightEngine(); - c.init(true, new KeyParameter(key)); - counter[0] = 1; - c.processBlock(counter, 0, output, 0); - counter[0] = 2; - c.processBlock(counter, 0, newKey, 0); - counter[0] = 3; - c.processBlock(counter, 0, newKey, 16); - System.arraycopy(newKey, 0, key, 0, 32); - // The first self-test vector should match the first output block - assertArrayEquals(SELF_TEST_VECTOR_1, output); - // Calculate the second output block and the new key before reseeding - c.init(true, new KeyParameter(key)); - counter[0] = 4; - c.processBlock(counter, 0, output, 0); - counter[0] = 5; - c.processBlock(counter, 0, newKey, 0); - counter[0] = 6; - c.processBlock(counter, 0, newKey, 16); - System.arraycopy(newKey, 0, key, 0, 32); - // The second self-test vector should match the second output block - assertArrayEquals(SELF_TEST_VECTOR_2, output); - // Calculate the new key after reseeding - digest.update(key); - digest.update(seed); - digest.digest(key, 0, 32); - // Calculate the third output block - c.init(true, new KeyParameter(key)); - counter[0] = 8; - c.processBlock(counter, 0, output, 0); - // The third self-test vector should match the third output block - assertArrayEquals(SELF_TEST_VECTOR_3, output); - } -} diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/HashTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/HashTest.java index 482afc045152aa407a8f8b9b05b802e9209dc341..bce8b720eae3c79c3bfb9f139e73e1482af5a92e 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/HashTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/HashTest.java @@ -2,7 +2,7 @@ package org.briarproject.bramble.crypto; import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.test.BrambleTestCase; -import org.briarproject.bramble.test.TestSeedProvider; +import org.briarproject.bramble.test.TestSecureRandomProvider; import org.briarproject.bramble.test.TestUtils; import org.junit.Test; @@ -21,7 +21,7 @@ public class HashTest extends BrambleTestCase { private final byte[] inputBytes2 = new byte[0]; public HashTest() { - crypto = new CryptoComponentImpl(new TestSeedProvider()); + crypto = new CryptoComponentImpl(new TestSecureRandomProvider()); } @Test diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyAgreementTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyAgreementTest.java index 0a0e826dc92445b75b191fc1a4fe6e85d948d241..ad3b0dad6bb1b3c2d8a5d5cbe0662c4960be26d3 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyAgreementTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyAgreementTest.java @@ -3,9 +3,9 @@ package org.briarproject.bramble.crypto; import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.KeyPair; import org.briarproject.bramble.api.crypto.SecretKey; -import org.briarproject.bramble.api.system.SeedProvider; +import org.briarproject.bramble.api.system.SecureRandomProvider; import org.briarproject.bramble.test.BrambleTestCase; -import org.briarproject.bramble.test.TestSeedProvider; +import org.briarproject.bramble.test.TestSecureRandomProvider; import org.junit.Test; import static org.junit.Assert.assertArrayEquals; @@ -14,8 +14,9 @@ public class KeyAgreementTest extends BrambleTestCase { @Test public void testDeriveMasterSecret() throws Exception { - SeedProvider seedProvider = new TestSeedProvider(); - CryptoComponent crypto = new CryptoComponentImpl(seedProvider); + SecureRandomProvider + secureRandomProvider = new TestSecureRandomProvider(); + CryptoComponent crypto = new CryptoComponentImpl(secureRandomProvider); KeyPair aPair = crypto.generateAgreementKeyPair(); byte[] aPub = aPair.getPublic().getEncoded(); KeyPair bPair = crypto.generateAgreementKeyPair(); @@ -27,8 +28,9 @@ public class KeyAgreementTest extends BrambleTestCase { @Test public void testDeriveSharedSecret() throws Exception { - SeedProvider seedProvider = new TestSeedProvider(); - CryptoComponent crypto = new CryptoComponentImpl(seedProvider); + SecureRandomProvider + secureRandomProvider = new TestSecureRandomProvider(); + CryptoComponent crypto = new CryptoComponentImpl(secureRandomProvider); KeyPair aPair = crypto.generateAgreementKeyPair(); byte[] aPub = aPair.getPublic().getEncoded(); KeyPair bPair = crypto.generateAgreementKeyPair(); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyDerivationTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyDerivationTest.java index 616833c470b8f0d4217acd18519e206d2116e14e..0e0e7a69f7debff57300f5ae1af0d495c249b739 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyDerivationTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyDerivationTest.java @@ -1,20 +1,24 @@ package org.briarproject.bramble.crypto; +import org.briarproject.bramble.api.Bytes; import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.transport.TransportKeys; import org.briarproject.bramble.test.BrambleTestCase; -import org.briarproject.bramble.test.TestSeedProvider; +import org.briarproject.bramble.test.TestSecureRandomProvider; import org.briarproject.bramble.test.TestUtils; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class KeyDerivationTest extends BrambleTestCase { @@ -23,7 +27,7 @@ public class KeyDerivationTest extends BrambleTestCase { private final SecretKey master; public KeyDerivationTest() { - crypto = new CryptoComponentImpl(new TestSeedProvider()); + crypto = new CryptoComponentImpl(new TestSecureRandomProvider()); master = TestUtils.getSecretKey(); } @@ -156,11 +160,7 @@ public class KeyDerivationTest extends BrambleTestCase { } private void assertAllDifferent(List<SecretKey> keys) { - for (SecretKey ki : keys) { - for (SecretKey kj : keys) { - if (ki == kj) assertArrayEquals(ki.getBytes(), kj.getBytes()); - else assertFalse(Arrays.equals(ki.getBytes(), kj.getBytes())); - } - } + Set<Bytes> set = new HashSet<Bytes>(); + for (SecretKey k : keys) assertTrue(set.add(new Bytes(k.getBytes()))); } } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyEncodingAndParsingTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyEncodingAndParsingTest.java index 3a6f011f87ff2dcfa0479e1b130c98ce76123fc9..4eb7516407b0086f211ca03211766dba9ea1cbb6 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyEncodingAndParsingTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyEncodingAndParsingTest.java @@ -5,7 +5,7 @@ import org.briarproject.bramble.api.crypto.KeyParser; import org.briarproject.bramble.api.crypto.PrivateKey; import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.test.BrambleTestCase; -import org.briarproject.bramble.test.TestSeedProvider; +import org.briarproject.bramble.test.TestSecureRandomProvider; import org.briarproject.bramble.test.TestUtils; import org.junit.Test; @@ -19,7 +19,7 @@ import static org.junit.Assert.assertTrue; public class KeyEncodingAndParsingTest extends BrambleTestCase { private final CryptoComponentImpl crypto = - new CryptoComponentImpl(new TestSeedProvider()); + new CryptoComponentImpl(new TestSecureRandomProvider()); @Test public void testAgreementPublicKeyLength() throws Exception { diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/MacTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/MacTest.java index 3699e601e810d9588830ba52d4fbdc8e30a46c41..f6760bf3e66ace6db806c241d129c11b95ddc2a2 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/MacTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/MacTest.java @@ -3,7 +3,7 @@ package org.briarproject.bramble.crypto; import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.test.BrambleTestCase; -import org.briarproject.bramble.test.TestSeedProvider; +import org.briarproject.bramble.test.TestSecureRandomProvider; import org.briarproject.bramble.test.TestUtils; import org.junit.Test; @@ -22,7 +22,7 @@ public class MacTest extends BrambleTestCase { private final byte[] inputBytes2 = new byte[0]; public MacTest() { - crypto = new CryptoComponentImpl(new TestSeedProvider()); + crypto = new CryptoComponentImpl(new TestSecureRandomProvider()); } @Test diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/PasswordBasedKdfTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/PasswordBasedKdfTest.java index f92b0fef69dc429ef45258b16a714c7fa90a179d..efdd90dc655b053bcc713ce91d7bff3fc1a6912b 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/PasswordBasedKdfTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/PasswordBasedKdfTest.java @@ -1,7 +1,7 @@ package org.briarproject.bramble.crypto; import org.briarproject.bramble.test.BrambleTestCase; -import org.briarproject.bramble.test.TestSeedProvider; +import org.briarproject.bramble.test.TestSecureRandomProvider; import org.briarproject.bramble.test.TestUtils; import org.junit.Test; @@ -15,7 +15,7 @@ import static org.junit.Assert.assertTrue; public class PasswordBasedKdfTest extends BrambleTestCase { private final CryptoComponentImpl crypto = - new CryptoComponentImpl(new TestSeedProvider()); + new CryptoComponentImpl(new TestSecureRandomProvider()); @Test public void testEncryptionAndDecryption() { diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/PseudoSecureRandom.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/PseudoSecureRandom.java new file mode 100644 index 0000000000000000000000000000000000000000..92702ca90a006570043ce5f154634cfd27adc421 --- /dev/null +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/PseudoSecureRandom.java @@ -0,0 +1,48 @@ +package org.briarproject.bramble.crypto; + +import org.briarproject.bramble.api.crypto.PseudoRandom; + +import java.security.Provider; +import java.security.SecureRandom; +import java.security.SecureRandomSpi; + +class PseudoSecureRandom extends SecureRandom { + + private static final Provider PROVIDER = new PseudoSecureRandomProvider(); + + PseudoSecureRandom(byte[] seed) { + super(new PseudoSecureRandomSpi(seed), PROVIDER); + } + + private static class PseudoSecureRandomSpi extends SecureRandomSpi { + + private final PseudoRandom pseudoRandom; + + private PseudoSecureRandomSpi(byte[] seed) { + pseudoRandom = new PseudoRandomImpl(seed); + } + + @Override + protected byte[] engineGenerateSeed(int length) { + return pseudoRandom.nextBytes(length); + } + + @Override + protected void engineNextBytes(byte[] b) { + byte[] random = pseudoRandom.nextBytes(b.length); + System.arraycopy(random, 0, b, 0, b.length); + } + + @Override + protected void engineSetSeed(byte[] seed) { + // Thank you for your input + } + } + + private static class PseudoSecureRandomProvider extends Provider { + + private PseudoSecureRandomProvider() { + super("PseudoSecureRandom", 1.0, "Only for testing"); + } + } +} diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/SignatureTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/SignatureTest.java index 017ba3a3ba2896ef73e6ae5152ca718e2a1ac2ad..c11444c63475fe493ecefa5634b7b2d5c1884543 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/SignatureTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/SignatureTest.java @@ -3,7 +3,7 @@ package org.briarproject.bramble.crypto; import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.KeyPair; import org.briarproject.bramble.test.BrambleTestCase; -import org.briarproject.bramble.test.TestSeedProvider; +import org.briarproject.bramble.test.TestSecureRandomProvider; import org.briarproject.bramble.test.TestUtils; import org.junit.Test; @@ -22,7 +22,7 @@ public class SignatureTest extends BrambleTestCase { private final byte[] inputBytes = TestUtils.getRandomBytes(123); public SignatureTest() { - crypto = new CryptoComponentImpl(new TestSeedProvider()); + crypto = new CryptoComponentImpl(new TestSecureRandomProvider()); KeyPair k = crypto.generateSignatureKeyPair(); publicKey = k.getPublic().getEncoded(); privateKey = k.getPrivate().getEncoded(); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/system/LinuxSecureRandomProviderTest.java b/bramble-core/src/test/java/org/briarproject/bramble/system/LinuxSecureRandomProviderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8c4190ac98d35a807755c53f4e39e2e2a2b5044c --- /dev/null +++ b/bramble-core/src/test/java/org/briarproject/bramble/system/LinuxSecureRandomProviderTest.java @@ -0,0 +1,57 @@ +package org.briarproject.bramble.system; + +import org.briarproject.bramble.test.BrambleTestCase; +import org.briarproject.bramble.test.TestUtils; +import org.briarproject.bramble.util.OsUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.security.Provider; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class LinuxSecureRandomProviderTest extends BrambleTestCase { + + private final File testDir = TestUtils.getTestDirectory(); + + @Before + public void setUp() { + testDir.mkdirs(); + } + + @Test + public void testGetProviderWritesToRandomDeviceOnFirstCall() + throws Exception { + if (!(OsUtils.isLinux())) { + System.err.println("WARNING: Skipping test, can't run on this OS"); + return; + } + // Redirect the provider's output to a file + File urandom = new File(testDir, "urandom"); + urandom.delete(); + assertTrue(urandom.createNewFile()); + assertEquals(0, urandom.length()); + LinuxSecureRandomProvider p = new LinuxSecureRandomProvider(urandom); + // Getting a provider should write entropy to the file + Provider provider = p.getProvider(); + assertNotNull(provider); + assertEquals("LinuxPRNG", provider.getName()); + // There should be at least 16 bytes from the clock, 8 from the runtime + long length = urandom.length(); + assertTrue(length >= 24); + // Getting another provider should not write to the file again + provider = p.getProvider(); + assertNotNull(provider); + assertEquals("LinuxPRNG", provider.getName()); + assertEquals(length, urandom.length()); + } + + @After + public void tearDown() { + TestUtils.deleteTestDirectory(testDir); + } +} diff --git a/bramble-core/src/test/java/org/briarproject/bramble/system/LinuxSecureRandomSpiTest.java b/bramble-core/src/test/java/org/briarproject/bramble/system/LinuxSecureRandomSpiTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4a3ac7313d2428fe4f4ab0fc994a8096d3b0e167 --- /dev/null +++ b/bramble-core/src/test/java/org/briarproject/bramble/system/LinuxSecureRandomSpiTest.java @@ -0,0 +1,128 @@ +package org.briarproject.bramble.system; + +import org.briarproject.bramble.api.Bytes; +import org.briarproject.bramble.test.BrambleTestCase; +import org.briarproject.bramble.test.TestUtils; +import org.briarproject.bramble.util.IoUtils; +import org.briarproject.bramble.util.OsUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.HashSet; +import java.util.Set; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + + +public class LinuxSecureRandomSpiTest extends BrambleTestCase { + + private static final File RANDOM_DEVICE = new File("/dev/urandom"); + private static final int SEED_BYTES = 32; + + private final File testDir = TestUtils.getTestDirectory(); + + @Before + public void setUp() { + testDir.mkdirs(); + } + + @Test + public void testSeedsAreDistinct() { + if (!(OsUtils.isLinux())) { + System.err.println("WARNING: Skipping test, can't run on this OS"); + return; + } + Set<Bytes> seeds = new HashSet<Bytes>(); + LinuxSecureRandomSpi engine = new LinuxSecureRandomSpi(); + for (int i = 0; i < 1000; i++) { + byte[] seed = engine.engineGenerateSeed(SEED_BYTES); + assertEquals(SEED_BYTES, seed.length); + assertTrue(seeds.add(new Bytes(seed))); + } + } + + @Test + public void testEngineSetSeedWritesToRandomDevice() throws Exception { + if (!(OsUtils.isLinux())) { + System.err.println("WARNING: Skipping test, can't run on this OS"); + return; + } + // Redirect the engine's output to a file + File urandom = new File(testDir, "urandom"); + urandom.delete(); + assertTrue(urandom.createNewFile()); + assertEquals(0, urandom.length()); + // Generate a seed + byte[] seed = TestUtils.getRandomBytes(SEED_BYTES); + // Check that the engine writes the seed to the file + LinuxSecureRandomSpi engine = new LinuxSecureRandomSpi(RANDOM_DEVICE, + urandom); + engine.engineSetSeed(seed); + assertEquals(SEED_BYTES, urandom.length()); + byte[] written = new byte[SEED_BYTES]; + FileInputStream in = new FileInputStream(urandom); + IoUtils.read(in, written); + in.close(); + assertArrayEquals(seed, written); + } + + @Test + public void testEngineNextBytesReadsFromRandomDevice() throws Exception { + if (!(OsUtils.isLinux())) { + System.err.println("WARNING: Skipping test, can't run on this OS"); + return; + } + // Generate some entropy + byte[] entropy = TestUtils.getRandomBytes(SEED_BYTES); + // Write the entropy to a file + File urandom = new File(testDir, "urandom"); + urandom.delete(); + FileOutputStream out = new FileOutputStream(urandom); + out.write(entropy); + out.flush(); + out.close(); + assertTrue(urandom.exists()); + assertEquals(SEED_BYTES, urandom.length()); + // Check that the engine reads from the file + LinuxSecureRandomSpi engine = new LinuxSecureRandomSpi(urandom, + RANDOM_DEVICE); + byte[] b = new byte[SEED_BYTES]; + engine.engineNextBytes(b); + assertArrayEquals(entropy, b); + } + + @Test + public void testEngineGenerateSeedReadsFromRandomDevice() throws Exception { + if (!(OsUtils.isLinux())) { + System.err.println("WARNING: Skipping test, can't run on this OS"); + return; + } + // Generate some entropy + byte[] entropy = TestUtils.getRandomBytes(SEED_BYTES); + // Write the entropy to a file + File urandom = new File(testDir, "urandom"); + urandom.delete(); + FileOutputStream out = new FileOutputStream(urandom); + out.write(entropy); + out.flush(); + out.close(); + assertTrue(urandom.exists()); + assertEquals(SEED_BYTES, urandom.length()); + // Check that the engine reads from the file + LinuxSecureRandomSpi engine = new LinuxSecureRandomSpi(urandom, + RANDOM_DEVICE); + byte[] b = engine.engineGenerateSeed(SEED_BYTES); + assertArrayEquals(entropy, b); + } + + @After + public void tearDown() { + TestUtils.deleteTestDirectory(testDir); + } +} diff --git a/bramble-core/src/test/java/org/briarproject/bramble/system/LinuxSeedProviderTest.java b/bramble-core/src/test/java/org/briarproject/bramble/system/LinuxSeedProviderTest.java deleted file mode 100644 index 0e0fe119c947427f93ce4e461f064cf31e7be5ef..0000000000000000000000000000000000000000 --- a/bramble-core/src/test/java/org/briarproject/bramble/system/LinuxSeedProviderTest.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.briarproject.bramble.system; - -import org.briarproject.bramble.api.Bytes; -import org.briarproject.bramble.test.BrambleTestCase; -import org.briarproject.bramble.test.TestUtils; -import org.briarproject.bramble.util.OsUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.File; -import java.io.FileOutputStream; -import java.util.HashSet; -import java.util.Set; - -import static org.briarproject.bramble.api.system.SeedProvider.SEED_BYTES; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class LinuxSeedProviderTest extends BrambleTestCase { - - private final File testDir = TestUtils.getTestDirectory(); - - @Before - public void setUp() { - testDir.mkdirs(); - } - - @Test - public void testSeedAppearsSane() { - if (!(OsUtils.isLinux())) { - System.err.println("WARNING: Skipping test, can't run on this OS"); - return; - } - Set<Bytes> seeds = new HashSet<Bytes>(); - LinuxSeedProvider p = new LinuxSeedProvider(); - for (int i = 0; i < 1000; i++) { - byte[] seed = p.getSeed(); - assertEquals(SEED_BYTES, seed.length); - assertTrue(seeds.add(new Bytes(seed))); - } - } - - @Test - public void testEntropyIsWrittenToPool() throws Exception { - if (!(OsUtils.isLinux())) { - System.err.println("WARNING: Skipping test, can't run on this OS"); - return; - } - // Redirect the provider's entropy to a file - File urandom = new File(testDir, "urandom"); - urandom.delete(); - assertTrue(urandom.createNewFile()); - assertEquals(0, urandom.length()); - String path = urandom.getAbsolutePath(); - LinuxSeedProvider p = new LinuxSeedProvider(path, "/dev/urandom"); - p.getSeed(); - // There should be 16 bytes from the clock, plus network interfaces - assertTrue(urandom.length() > 20); - } - - @Test - public void testSeedIsReadFromPool() throws Exception { - if (!(OsUtils.isLinux())) { - System.err.println("WARNING: Skipping test, can't run on this OS"); - return; - } - // Generate a seed - byte[] seed = TestUtils.getRandomBytes(SEED_BYTES); - // Write the seed to a file - File urandom = new File(testDir, "urandom"); - urandom.delete(); - FileOutputStream out = new FileOutputStream(urandom); - out.write(seed); - out.flush(); - out.close(); - assertTrue(urandom.exists()); - assertEquals(SEED_BYTES, urandom.length()); - // Check that the provider reads the seed from the file - String path = urandom.getAbsolutePath(); - LinuxSeedProvider p = new LinuxSeedProvider("/dev/urandom", path); - assertArrayEquals(seed, p.getSeed()); - } - - @After - public void tearDown() { - TestUtils.deleteTestDirectory(testDir); - } -} diff --git a/bramble-core/src/test/java/org/briarproject/bramble/test/TestSecureRandomProvider.java b/bramble-core/src/test/java/org/briarproject/bramble/test/TestSecureRandomProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..c34c227d16e868dc0998fb80038848203f14e266 --- /dev/null +++ b/bramble-core/src/test/java/org/briarproject/bramble/test/TestSecureRandomProvider.java @@ -0,0 +1,16 @@ +package org.briarproject.bramble.test; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.system.SecureRandomProvider; + +import java.security.Provider; + +@NotNullByDefault +public class TestSecureRandomProvider implements SecureRandomProvider { + + @Override + public Provider getProvider() { + // Use the default provider + return null; + } +} diff --git a/bramble-core/src/test/java/org/briarproject/bramble/test/TestSeedProvider.java b/bramble-core/src/test/java/org/briarproject/bramble/test/TestSeedProvider.java deleted file mode 100644 index a149bec8b6ea8ab25f475e2ff5c447dc48b3a09d..0000000000000000000000000000000000000000 --- a/bramble-core/src/test/java/org/briarproject/bramble/test/TestSeedProvider.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.briarproject.bramble.test; - -import org.briarproject.bramble.api.nullsafety.NotNullByDefault; -import org.briarproject.bramble.api.system.SeedProvider; - -@NotNullByDefault -public class TestSeedProvider implements SeedProvider { - - @Override - public byte[] getSeed() { - return TestUtils.getRandomBytes(32); - } -} diff --git a/bramble-core/src/test/java/org/briarproject/bramble/test/TestSeedProviderModule.java b/bramble-core/src/test/java/org/briarproject/bramble/test/TestSeedProviderModule.java index ce8650d264881ee17c3f6c9739045fdb2997dd27..b2e4db7d9c29f80b0fceba4191cf963523e92786 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/test/TestSeedProviderModule.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/test/TestSeedProviderModule.java @@ -1,6 +1,6 @@ package org.briarproject.bramble.test; -import org.briarproject.bramble.api.system.SeedProvider; +import org.briarproject.bramble.api.system.SecureRandomProvider; import javax.inject.Singleton; @@ -12,7 +12,7 @@ public class TestSeedProviderModule { @Provides @Singleton - SeedProvider provideSeedProvider() { - return new TestSeedProvider(); + SecureRandomProvider provideSeedProvider() { + return new TestSecureRandomProvider(); } } diff --git a/bramble-j2se/src/main/java/org/briarproject/bramble/system/DesktopSecureRandomModule.java b/bramble-j2se/src/main/java/org/briarproject/bramble/system/DesktopSecureRandomModule.java new file mode 100644 index 0000000000000000000000000000000000000000..65246870c55915b849605fa1be0b6bf9ed404117 --- /dev/null +++ b/bramble-j2se/src/main/java/org/briarproject/bramble/system/DesktopSecureRandomModule.java @@ -0,0 +1,19 @@ +package org.briarproject.bramble.system; + +import org.briarproject.bramble.api.system.SecureRandomProvider; +import org.briarproject.bramble.util.OsUtils; + +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +@Module +public class DesktopSecureRandomModule { + + @Provides + @Singleton + SecureRandomProvider provideSecureRandomProvider() { + return OsUtils.isLinux() ? new LinuxSecureRandomProvider() : null; + } +} diff --git a/bramble-j2se/src/main/java/org/briarproject/bramble/system/DesktopSeedProviderModule.java b/bramble-j2se/src/main/java/org/briarproject/bramble/system/DesktopSeedProviderModule.java deleted file mode 100644 index d603f7a1344243edb2e5089bffbcee4619bf0f53..0000000000000000000000000000000000000000 --- a/bramble-j2se/src/main/java/org/briarproject/bramble/system/DesktopSeedProviderModule.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.briarproject.bramble.system; - -import org.briarproject.bramble.api.system.SeedProvider; -import org.briarproject.bramble.util.OsUtils; - -import javax.inject.Singleton; - -import dagger.Module; -import dagger.Provides; - -@Module -public class DesktopSeedProviderModule { - - @Provides - @Singleton - SeedProvider provideSeedProvider() { - return OsUtils.isLinux() ? new LinuxSeedProvider() : null; - } -}