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

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