diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoComponent.java index c104f61d1310111389eb053b81dcaf6257a93e08..f4f065c97393dea173a93d788b9f757700405fcb 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoComponent.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoComponent.java @@ -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); /** 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 435b453ca1b04ec2a089b5a212093f31502f76c9..25969d0eb36dc9a68a26bcf85de9db7bdc9214db 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 @@ -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; - } } 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 a40b656282556a5660b23973a5b611f4793dec3e..25d24995d5ddf45b5a9aefea69fe1c5c101d0acd 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 @@ -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 diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/PasswordBasedKdf.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/PasswordBasedKdf.java new file mode 100644 index 0000000000000000000000000000000000000000..60604c6c2ef64eb62bc31d692aa3b81b98b480d7 --- /dev/null +++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/PasswordBasedKdf.java @@ -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); +} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/ScryptKdf.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/ScryptKdf.java new file mode 100644 index 0000000000000000000000000000000000000000..b5cec690619740e6aca789e28dd6339be99be6f5 --- /dev/null +++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/ScryptKdf.java @@ -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; + } +} 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 dcd3177ba718ba875b062e664c2b8ae77900d5f5..56eda7c87587d266c8f4b1ee9cd8eebf57c4a7e3 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 @@ -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 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 5a3568631ca95d7846ae58df0ae5e3c1015d4285..d035bbe4b39f2b72e6c7e92c13b1c21bef05f046 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 @@ -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(); 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 805816e9233064e35064335069014e438d38670d..81f73f8d28f410a5c434d4d107815c416ff59d37 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 @@ -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"); 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 4eb7516407b0086f211ca03211766dba9ea1cbb6..a7136e5cd59714b530e78c6b344704ba1ea73ece 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 @@ -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 { 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 8541c4a1d3c5ed4193700698c41d5358bc08fd67..7fb0717b79746ff19c8f31893fdb23ed9f935675 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 @@ -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); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/PasswordBasedKdfTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/PasswordBasedEncryptionTest.java similarity index 60% rename from bramble-core/src/test/java/org/briarproject/bramble/crypto/PasswordBasedKdfTest.java rename to bramble-core/src/test/java/org/briarproject/bramble/crypto/PasswordBasedEncryptionTest.java index efdd90dc655b053bcc713ce91d7bff3fc1a6912b..5efc3593ebd79ddd9485a79a272586f4d7c3ae76 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/PasswordBasedKdfTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/PasswordBasedEncryptionTest.java @@ -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); - } } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/ScryptKdfTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/ScryptKdfTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d53925245532048a202702c6a0ddad83baa964e0 --- /dev/null +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/ScryptKdfTest.java @@ -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); + } + } +} 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 1abe4a71a56ad55252e994daa1a60154d7ace798..09561c8c69d1fa36aa36c2a5ad82564df37143e0 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 @@ -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(); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/sync/SyncIntegrationTestComponent.java b/bramble-core/src/test/java/org/briarproject/bramble/sync/SyncIntegrationTestComponent.java index 6c0ffa19cb24562228d945305862a1718718c20c..a714520dd5df088f882a160d33b3d7c6a48be117 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/sync/SyncIntegrationTestComponent.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/sync/SyncIntegrationTestComponent.java @@ -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 { diff --git a/bramble-core/src/test/java/org/briarproject/bramble/test/TestSeedProviderModule.java b/bramble-core/src/test/java/org/briarproject/bramble/test/TestSecureRandomModule.java similarity index 63% rename from bramble-core/src/test/java/org/briarproject/bramble/test/TestSeedProviderModule.java rename to bramble-core/src/test/java/org/briarproject/bramble/test/TestSecureRandomModule.java index b2e4db7d9c29f80b0fceba4191cf963523e92786..97cdd0cf31496dc93eb3da731ac82ab5815029ed 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/test/TestSeedProviderModule.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/test/TestSecureRandomModule.java @@ -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(); } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordFragment.java index 80b8e04e417e7cbeca12002bdedd26118754236e..3b5f788b746aaa4739e8fca9358baf6beab9e1e3 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordFragment.java @@ -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(); } diff --git a/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java index ce5ec5a00dfecbc9d2b5c8b6f0af92abb5d776e1..0a8fbfbe62db6c661dcfbe89008aa432ede1b055 100644 --- a/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java +++ b/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java @@ -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, diff --git a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java index 538d4def320ba2cbbbea1e9a1cd0150bf77f7a4d..bc0ea62410713a6ae9f4a3f5034c8e10c187111b 100644 --- a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java +++ b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java @@ -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, diff --git a/briar-core/src/test/java/org/briarproject/briar/messaging/MessageSizeIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/messaging/MessageSizeIntegrationTestComponent.java index 2c91a0bd87bb4ac536309505b2620d22b8ff12e8..42b27da6f3c4265d021bb376316f65cc2f1944ab 100644 --- a/briar-core/src/test/java/org/briarproject/briar/messaging/MessageSizeIntegrationTestComponent.java +++ b/briar-core/src/test/java/org/briarproject/briar/messaging/MessageSizeIntegrationTestComponent.java @@ -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, diff --git a/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java index 085d28ae1ceff45921da742e71bfc856d1295e5e..d740859aa130141e1c1fe5fee92fa3ad2e3ee8e0 100644 --- a/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java +++ b/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java @@ -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, diff --git a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTestComponent.java index 679d7772aa7798c863aa4129dfbd27e347760b97..1b2344d3add2760d94dab0aae8f09babbc052a0d 100644 --- a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTestComponent.java +++ b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTestComponent.java @@ -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,