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 000000000..502e7b982
--- /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 52d15db5e..000000000
--- 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 e5976ff99..79fbf44b5 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 000000000..7d821ba2c
--- /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 2d5c147f1..000000000
--- 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 82c9d50d6..000000000
--- 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 ae25da4e1..197ef7973 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 accfaf527..6b3ea5295 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 2bd71fa78..000000000
--- 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, Practical Cryptography, chapter 6.
- *
- * "Let h be an interative hash function. The hash function hd is
- * defined by hd := 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 5c36a931f..000000000
--- 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, Practical Cryptography, 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 62e609c96..000000000
--- 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 fb02df047..1eabb29df 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 000000000..c442895a2
--- /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 ifaces =
+ Collections.list(NetworkInterface.getNetworkInterfaces());
+ for (NetworkInterface i : ifaces) {
+ List 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 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 000000000..c63c02b05
--- /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 000000000..6b4790ada
--- /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 e4141a417..000000000
--- 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 ifaces =
- Collections.list(NetworkInterface.getNetworkInterfaces());
- for (NetworkInterface i : ifaces) {
- List 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 ce3d03e44..9be3dc0dd 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 c1573f610..000000000
--- 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 d685ce11f..000000000
--- 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 482afc045..bce8b720e 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 0a0e826dc..ad3b0dad6 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 616833c47..0e0e7a69f 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 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 set = new HashSet();
+ 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 3a6f011f8..4eb751640 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 3699e601e..f6760bf3e 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 f92b0fef6..efdd90dc6 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 000000000..92702ca90
--- /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 017ba3a3b..c11444c63 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 000000000..8c4190ac9
--- /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 000000000..4a3ac7313
--- /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 seeds = new HashSet();
+ 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 0e0fe119c..000000000
--- 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 seeds = new HashSet();
- 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 000000000..c34c227d1
--- /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 a149bec8b..000000000
--- 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 ce8650d26..b2e4db7d9 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 000000000..65246870c
--- /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 d603f7a13..000000000
--- 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;
- }
-}