Use scrypt for password-based key derivation.

This commit is contained in:
akwizgran
2018-01-12 15:52:41 +00:00
parent 3e55be8a82
commit 6bdb099aa9
21 changed files with 215 additions and 121 deletions

View File

@@ -1,8 +1,13 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import javax.annotation.Nullable;
@NotNullByDefault
public interface CryptoComponent {
SecretKey generateSecretKey();
@@ -124,6 +129,7 @@ public interface CryptoComponent {
* given password. Returns null if the ciphertext cannot be decrypted and
* authenticated (for example, if the password is wrong).
*/
@Nullable
byte[] decryptWithPassword(byte[] ciphertext, String password);
/**

View File

@@ -10,31 +10,25 @@ 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.api.crypto.SecretKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.SecureRandomProvider;
import org.briarproject.bramble.util.ByteUtils;
import org.briarproject.bramble.util.StringUtils;
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
import org.spongycastle.crypto.CipherParameters;
import org.spongycastle.crypto.CryptoException;
import org.spongycastle.crypto.Digest;
import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
import org.spongycastle.crypto.digests.Blake2bDigest;
import org.spongycastle.crypto.digests.SHA256Digest;
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator;
import org.spongycastle.crypto.params.ECKeyGenerationParameters;
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.spongycastle.crypto.params.ECPublicKeyParameters;
import org.spongycastle.crypto.params.KeyParameter;
import 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;
import java.util.logging.Logger;
import javax.inject.Inject;
@@ -43,6 +37,7 @@ import static java.util.logging.Level.INFO;
import static org.briarproject.bramble.crypto.EllipticCurveConstants.PARAMETERS;
import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
@NotNullByDefault
class CryptoComponentImpl implements CryptoComponent {
private static final Logger LOG =
@@ -53,10 +48,9 @@ class CryptoComponentImpl implements CryptoComponent {
private static final int ED_KEY_PAIR_BITS = 256;
private static final int STORAGE_IV_BYTES = 24; // 196 bits
private static final int PBKDF_SALT_BYTES = 32; // 256 bits
private static final int PBKDF_TARGET_MILLIS = 500;
private static final int PBKDF_SAMPLES = 30;
private final SecureRandom secureRandom;
private final PasswordBasedKdf passwordBasedKdf;
private final ECKeyPairGenerator agreementKeyPairGenerator;
private final ECKeyPairGenerator signatureKeyPairGenerator;
private final KeyParser agreementKeyParser, signatureKeyParser;
@@ -65,7 +59,8 @@ class CryptoComponentImpl implements CryptoComponent {
private final KeyParser edKeyParser;
@Inject
CryptoComponentImpl(SecureRandomProvider secureRandomProvider) {
CryptoComponentImpl(SecureRandomProvider secureRandomProvider,
PasswordBasedKdf passwordBasedKdf) {
if (LOG.isLoggable(INFO)) {
SecureRandom defaultSecureRandom = new SecureRandom();
String name = defaultSecureRandom.getProvider().getName();
@@ -85,6 +80,7 @@ class CryptoComponentImpl implements CryptoComponent {
}
}
secureRandom = new SecureRandom();
this.passwordBasedKdf = passwordBasedKdf;
ECKeyGenerationParameters params = new ECKeyGenerationParameters(
PARAMETERS, secureRandom);
agreementKeyPairGenerator = new ECKeyPairGenerator();
@@ -339,18 +335,18 @@ class CryptoComponentImpl implements CryptoComponent {
byte[] salt = new byte[PBKDF_SALT_BYTES];
secureRandom.nextBytes(salt);
// Calibrate the KDF
int iterations = chooseIterationCount(PBKDF_TARGET_MILLIS);
int cost = passwordBasedKdf.chooseCostParameter();
// Derive the key from the password
SecretKey key = new SecretKey(pbkdf2(password, salt, iterations));
SecretKey key = passwordBasedKdf.deriveKey(password, salt, cost);
// Generate a random IV
byte[] iv = new byte[STORAGE_IV_BYTES];
secureRandom.nextBytes(iv);
// The output contains the salt, iterations, IV, ciphertext and MAC
// The output contains the salt, cost parameter, IV, ciphertext and MAC
int outputLen = salt.length + INT_32_BYTES + iv.length + input.length
+ macBytes;
byte[] output = new byte[outputLen];
System.arraycopy(salt, 0, output, 0, salt.length);
ByteUtils.writeUint32(iterations, output, salt.length);
ByteUtils.writeUint32(cost, output, salt.length);
System.arraycopy(iv, 0, output, salt.length + INT_32_BYTES, iv.length);
// Initialise the cipher and encrypt the plaintext
try {
@@ -367,19 +363,19 @@ class CryptoComponentImpl implements CryptoComponent {
public byte[] decryptWithPassword(byte[] input, String password) {
AuthenticatedCipher cipher = new XSalsa20Poly1305AuthenticatedCipher();
int macBytes = cipher.getMacBytes();
// The input contains the salt, iterations, IV, ciphertext and MAC
// The input contains the salt, cost parameter, IV, ciphertext and MAC
if (input.length < PBKDF_SALT_BYTES + INT_32_BYTES + STORAGE_IV_BYTES
+ macBytes)
return null; // Invalid input
byte[] salt = new byte[PBKDF_SALT_BYTES];
System.arraycopy(input, 0, salt, 0, salt.length);
long iterations = ByteUtils.readUint32(input, salt.length);
if (iterations < 0 || iterations > Integer.MAX_VALUE)
return null; // Invalid iteration count
long cost = ByteUtils.readUint32(input, salt.length);
if (cost < 2 || cost > Integer.MAX_VALUE)
return null; // Invalid cost parameter
byte[] iv = new byte[STORAGE_IV_BYTES];
System.arraycopy(input, salt.length + INT_32_BYTES, iv, 0, iv.length);
// Derive the key from the password
SecretKey key = new SecretKey(pbkdf2(password, salt, (int) iterations));
SecretKey key = passwordBasedKdf.deriveKey(password, salt, (int) cost);
// Initialise the cipher
try {
cipher.init(false, key, iv);
@@ -411,64 +407,4 @@ class CryptoComponentImpl implements CryptoComponent {
public String asciiArmour(byte[] b, int lineLength) {
return AsciiArmour.wrap(b, lineLength);
}
// Password-based key derivation function - see PKCS#5 v2.1, section 5.2
private byte[] pbkdf2(String password, byte[] salt, int iterations) {
byte[] utf8 = StringUtils.toUtf8(password);
Digest digest = new SHA256Digest();
PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(digest);
gen.init(utf8, salt, iterations);
int keyLengthInBits = SecretKey.LENGTH * 8;
CipherParameters p = gen.generateDerivedParameters(keyLengthInBits);
return ((KeyParameter) p).getKey();
}
// Package access for testing
int chooseIterationCount(int targetMillis) {
List<Long> quickSamples = new ArrayList<>(PBKDF_SAMPLES);
List<Long> slowSamples = new ArrayList<>(PBKDF_SAMPLES);
long iterationNanos = 0, initNanos = 0;
while (iterationNanos <= 0 || initNanos <= 0) {
// Sample the running time with one iteration and two iterations
for (int i = 0; i < PBKDF_SAMPLES; i++) {
quickSamples.add(sampleRunningTime(1));
slowSamples.add(sampleRunningTime(2));
}
// Calculate the iteration time and the initialisation time
long quickMedian = median(quickSamples);
long slowMedian = median(slowSamples);
iterationNanos = slowMedian - quickMedian;
initNanos = quickMedian - iterationNanos;
if (LOG.isLoggable(INFO)) {
LOG.info("Init: " + initNanos + ", iteration: "
+ iterationNanos);
}
}
long targetNanos = targetMillis * 1000L * 1000L;
long iterations = (targetNanos - initNanos) / iterationNanos;
if (LOG.isLoggable(INFO)) LOG.info("Target iterations: " + iterations);
if (iterations < 1) return 1;
if (iterations > Integer.MAX_VALUE) return Integer.MAX_VALUE;
return (int) iterations;
}
private long sampleRunningTime(int iterations) {
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();
Digest digest = new SHA256Digest();
PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(digest);
gen.init(password, salt, iterations);
gen.generateDerivedParameters(keyLengthInBits);
return System.nanoTime() - start;
}
private long median(List<Long> list) {
int size = list.size();
if (size == 0) throw new IllegalArgumentException();
Collections.sort(list);
if (size % 2 == 1) return list.get(size / 2);
return list.get(size / 2 - 1) + list.get(size / 2) / 2;
}
}

View File

@@ -67,8 +67,9 @@ public class CryptoModule {
@Provides
@Singleton
CryptoComponent provideCryptoComponent(
SecureRandomProvider secureRandomProvider) {
return new CryptoComponentImpl(secureRandomProvider);
SecureRandomProvider secureRandomProvider,
ScryptKdf passwordBasedKdf) {
return new CryptoComponentImpl(secureRandomProvider, passwordBasedKdf);
}
@Provides

View File

@@ -0,0 +1,10 @@
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.SecretKey;
interface PasswordBasedKdf {
int chooseCostParameter();
SecretKey deriveKey(String password, byte[] salt, int cost);
}

View File

@@ -0,0 +1,62 @@
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.StringUtils;
import org.spongycastle.crypto.generators.SCrypt;
import java.util.logging.Logger;
import javax.inject.Inject;
import static java.util.logging.Level.INFO;
class ScryptKdf implements PasswordBasedKdf {
private static final Logger LOG =
Logger.getLogger(ScryptKdf.class.getName());
private static final int MIN_COST = 512; // Min parameter N
private static final int MAX_COST = 1024 * 1024; // Max parameter N
private static final int BLOCK_SIZE = 8; // Parameter r
private static final int PARALLELIZATION = 1; // Parameter p
private static final int TARGET_MS = 1000;
private final Clock clock;
@Inject
ScryptKdf(Clock clock) {
this.clock = clock;
}
@Override
public int chooseCostParameter() {
// Increase the cost from min to max while measuring performance
int cost = MIN_COST;
while (cost * 2 <= MAX_COST && measureDuration(cost) * 2 <= TARGET_MS)
cost *= 2;
if (LOG.isLoggable(INFO))
LOG.info("KDF cost parameter " + cost);
return cost;
}
private long measureDuration(int cost) {
byte[] password = new byte[16], salt = new byte[32];
long start = clock.currentTimeMillis();
SCrypt.generate(password, salt, cost, BLOCK_SIZE, PARALLELIZATION,
SecretKey.LENGTH);
return clock.currentTimeMillis() - start;
}
@Override
public SecretKey deriveKey(String password, byte[] salt, int cost) {
long start = System.currentTimeMillis();
byte[] passwordBytes = StringUtils.toUtf8(password);
SecretKey k = new SecretKey(SCrypt.generate(passwordBytes, salt, cost,
BLOCK_SIZE, PARALLELIZATION, SecretKey.LENGTH));
long duration = System.currentTimeMillis() - start;
if (LOG.isLoggable(INFO))
LOG.info("Deriving key from password took " + duration + " ms");
return k;
}
}

View File

@@ -22,7 +22,7 @@ public class HashTest extends BrambleTestCase {
private final byte[] inputBytes2 = new byte[0];
public HashTest() {
crypto = new CryptoComponentImpl(new TestSecureRandomProvider());
crypto = new CryptoComponentImpl(new TestSecureRandomProvider(), null);
}
@Test

View File

@@ -18,7 +18,7 @@ public class KeyAgreementTest extends BrambleTestCase {
@Test
public void testDeriveSharedSecret() throws Exception {
CryptoComponent crypto =
new CryptoComponentImpl(new TestSecureRandomProvider());
new CryptoComponentImpl(new TestSecureRandomProvider(), null);
KeyPair aPair = crypto.generateAgreementKeyPair();
KeyPair bPair = crypto.generateAgreementKeyPair();
Random random = new Random();

View File

@@ -24,7 +24,7 @@ import static org.junit.Assert.assertTrue;
public class KeyDerivationTest extends BrambleTestCase {
private final CryptoComponent crypto =
new CryptoComponentImpl(new TestSecureRandomProvider());
new CryptoComponentImpl(new TestSecureRandomProvider(), null);
private final TransportCrypto transportCrypto =
new TransportCryptoImpl(crypto);
private final TransportId transportId = new TransportId("id");

View File

@@ -19,7 +19,7 @@ import static org.junit.Assert.assertTrue;
public class KeyEncodingAndParsingTest extends BrambleTestCase {
private final CryptoComponentImpl crypto =
new CryptoComponentImpl(new TestSecureRandomProvider());
new CryptoComponentImpl(new TestSecureRandomProvider(), null);
@Test
public void testAgreementPublicKeyLength() throws Exception {

View File

@@ -17,7 +17,7 @@ import static org.junit.Assert.assertFalse;
public class MacTest extends BrambleTestCase {
private final CryptoComponent crypto =
new CryptoComponentImpl(new TestSecureRandomProvider());
new CryptoComponentImpl(new TestSecureRandomProvider(), null);
private final SecretKey key1 = getSecretKey(), key2 = getSecretKey();
private final String label1 = getRandomString(123);

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.system.SystemClock;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestSecureRandomProvider;
import org.briarproject.bramble.test.TestUtils;
@@ -8,14 +9,13 @@ import org.junit.Test;
import java.util.Random;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public class PasswordBasedKdfTest extends BrambleTestCase {
public class PasswordBasedEncryptionTest extends BrambleTestCase {
private final CryptoComponentImpl crypto =
new CryptoComponentImpl(new TestSecureRandomProvider());
new CryptoComponentImpl(new TestSecureRandomProvider(),
new ScryptKdf(new SystemClock()));
@Test
public void testEncryptionAndDecryption() {
@@ -37,17 +37,4 @@ public class PasswordBasedKdfTest extends BrambleTestCase {
byte[] output = crypto.decryptWithPassword(ciphertext, password);
assertNull(output);
}
@Test
public void testCalibration() {
// If the target time is unachievable, one iteration should be used
int iterations = crypto.chooseIterationCount(0);
assertEquals(1, iterations);
// If the target time is long, more than one iteration should be used
iterations = crypto.chooseIterationCount(10 * 1000);
assertTrue(iterations > 1);
// If the target time is very long, max iterations should be used
iterations = crypto.chooseIterationCount(Integer.MAX_VALUE);
assertEquals(Integer.MAX_VALUE, iterations);
}
}

View File

@@ -0,0 +1,87 @@
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.system.SystemClock;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Test;
import java.util.HashSet;
import java.util.Set;
import static junit.framework.TestCase.assertTrue;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertEquals;
public class ScryptKdfTest extends BrambleTestCase {
@Test
public void testPasswordAffectsKey() throws Exception {
PasswordBasedKdf kdf = new ScryptKdf(new SystemClock());
byte[] salt = getRandomBytes(32);
Set<Bytes> keys = new HashSet<>();
for (int i = 0; i < 100; i++) {
String password = getRandomString(16);
SecretKey key = kdf.deriveKey(password, salt, 256);
assertTrue(keys.add(new Bytes(key.getBytes())));
}
}
@Test
public void testSaltAffectsKey() throws Exception {
PasswordBasedKdf kdf = new ScryptKdf(new SystemClock());
String password = getRandomString(16);
Set<Bytes> keys = new HashSet<>();
for (int i = 0; i < 100; i++) {
byte[] salt = getRandomBytes(32);
SecretKey key = kdf.deriveKey(password, salt, 256);
assertTrue(keys.add(new Bytes(key.getBytes())));
}
}
@Test
public void testCostParameterAffectsKey() throws Exception {
PasswordBasedKdf kdf = new ScryptKdf(new SystemClock());
String password = getRandomString(16);
byte[] salt = getRandomBytes(32);
Set<Bytes> keys = new HashSet<>();
for (int cost = 2; cost <= 256; cost *= 2) {
SecretKey key = kdf.deriveKey(password, salt, cost);
assertTrue(keys.add(new Bytes(key.getBytes())));
}
}
@Test
public void testCalibration() throws Exception {
Clock clock = new ArrayClock(
0, 100, // Duration for cost 512
0, 200, // Duration for cost 1024
0, 400, // Duration for cost 2048
0, 800 // Duration for cost 4096
);
PasswordBasedKdf kdf = new ScryptKdf(clock);
assertEquals(4096, kdf.chooseCostParameter());
}
private static class ArrayClock implements Clock {
private final long[] times;
private int index = 0;
private ArrayClock(long... times) {
this.times = times;
}
@Override
public long currentTimeMillis() {
return times[index++];
}
@Override
public void sleep(long milliseconds) throws InterruptedException {
Thread.sleep(milliseconds);
}
}
}

View File

@@ -32,7 +32,7 @@ public abstract class SignatureTest extends BrambleTestCase {
byte[] publicKey, byte[] signature) throws GeneralSecurityException;
SignatureTest() {
crypto = new CryptoComponentImpl(new TestSecureRandomProvider());
crypto = new CryptoComponentImpl(new TestSecureRandomProvider(), null);
KeyPair k = generateKeyPair();
publicKey = k.getPublic().getEncoded();
privateKey = k.getPrivate().getEncoded();

View File

@@ -1,7 +1,8 @@
package org.briarproject.bramble.sync;
import org.briarproject.bramble.crypto.CryptoModule;
import org.briarproject.bramble.test.TestSeedProviderModule;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.test.TestSecureRandomModule;
import org.briarproject.bramble.transport.TransportModule;
import javax.inject.Singleton;
@@ -10,9 +11,10 @@ import dagger.Component;
@Singleton
@Component(modules = {
TestSeedProviderModule.class,
TestSecureRandomModule.class,
CryptoModule.class,
SyncModule.class,
SystemModule.class,
TransportModule.class
})
interface SyncIntegrationTestComponent {

View File

@@ -2,17 +2,14 @@ package org.briarproject.bramble.test;
import org.briarproject.bramble.api.system.SecureRandomProvider;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class TestSeedProviderModule {
public class TestSecureRandomModule {
@Provides
@Singleton
SecureRandomProvider provideSeedProvider() {
SecureRandomProvider provideSecureRandomProvider() {
return new TestSecureRandomProvider();
}
}

View File

@@ -1,11 +1,13 @@
package org.briarproject.briar.android.login;
import android.os.Bundle;
import android.os.IBinder;
import android.support.design.widget.TextInputEditText;
import android.support.design.widget.TextInputLayout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.ProgressBar;
@@ -13,6 +15,7 @@ import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.util.UiUtils;
import static android.content.Context.INPUT_METHOD_SERVICE;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
@@ -107,6 +110,9 @@ public class PasswordFragment extends SetupFragment {
progressBar.setVisibility(VISIBLE);
}
String password = passwordEntry.getText().toString();
IBinder token = passwordEntry.getWindowToken();
Object o = getContext().getSystemService(INPUT_METHOD_SERVICE);
((InputMethodManager) o).hideSoftInputFromWindow(token, 0);
setupController.setPassword(password);
setupController.showDozeOrCreateAccount();
}

View File

@@ -13,7 +13,7 @@ import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.bramble.test.TestPluginConfigModule;
import org.briarproject.bramble.test.TestSeedProviderModule;
import org.briarproject.bramble.test.TestSecureRandomModule;
import org.briarproject.bramble.test.TestSocksModule;
import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.briar.api.blog.BlogManager;
@@ -30,7 +30,7 @@ import dagger.Component;
@Component(modules = {
TestDatabaseModule.class,
TestPluginConfigModule.class,
TestSeedProviderModule.class,
TestSecureRandomModule.class,
TestSocksModule.class,
TestDnsModule.class,
LifecycleModule.class,

View File

@@ -13,7 +13,7 @@ import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.bramble.test.TestPluginConfigModule;
import org.briarproject.bramble.test.TestSeedProviderModule;
import org.briarproject.bramble.test.TestSecureRandomModule;
import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.briar.blog.BlogModule;
import org.briarproject.briar.client.BriarClientModule;
@@ -32,7 +32,7 @@ import dagger.Component;
@Component(modules = {
TestDatabaseModule.class,
TestPluginConfigModule.class,
TestSeedProviderModule.class,
TestSecureRandomModule.class,
BlogModule.class,
BriarClientModule.class,
ClientModule.class,

View File

@@ -10,7 +10,7 @@ import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.bramble.test.TestLifecycleModule;
import org.briarproject.bramble.test.TestSeedProviderModule;
import org.briarproject.bramble.test.TestSecureRandomModule;
import org.briarproject.briar.client.BriarClientModule;
import org.briarproject.briar.forum.ForumModule;
@@ -22,7 +22,7 @@ import dagger.Component;
@Component(modules = {
TestDatabaseModule.class,
TestLifecycleModule.class,
TestSeedProviderModule.class,
TestSecureRandomModule.class,
BriarClientModule.class,
ClientModule.class,
CryptoModule.class,

View File

@@ -20,7 +20,7 @@ import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.bramble.test.TestPluginConfigModule;
import org.briarproject.bramble.test.TestSeedProviderModule;
import org.briarproject.bramble.test.TestSecureRandomModule;
import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.briar.api.messaging.MessagingManager;
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
@@ -34,7 +34,7 @@ import dagger.Component;
@Component(modules = {
TestDatabaseModule.class,
TestPluginConfigModule.class,
TestSeedProviderModule.class,
TestSecureRandomModule.class,
BriarClientModule.class,
ClientModule.class,
ContactModule.class,

View File

@@ -22,7 +22,7 @@ import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.bramble.test.TestPluginConfigModule;
import org.briarproject.bramble.test.TestSeedProviderModule;
import org.briarproject.bramble.test.TestSecureRandomModule;
import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.briar.api.blog.BlogFactory;
import org.briarproject.briar.api.blog.BlogManager;
@@ -50,7 +50,7 @@ import dagger.Component;
@Component(modules = {
TestDatabaseModule.class,
TestPluginConfigModule.class,
TestSeedProviderModule.class,
TestSecureRandomModule.class,
BlogModule.class,
BriarClientModule.class,
ClientModule.class,