Don't try to erase secrets from memory.

1. The things we're really trying to protect - contact identities,
message contents, etc - can't be erased from memory because they're
encapsulated inside objects we don't control.

2. Long-term secrets can't be protected by erasing them from memory
because they're stored in the database and the database key has to be
held in memory whenever the app's running.

3. If the runtime uses a compacting garbage collector then we have no
way to ensure an object is erased from memory.

4. Trying to erase secrets from memory makes the code more complex.

Conclusion: Let's not try to protect secrets from an attacker who can
read arbitrary memory locations.
This commit is contained in:
akwizgran
2014-12-29 21:08:27 +00:00
parent f316d64afa
commit 358166bc12
28 changed files with 211 additions and 557 deletions

View File

@@ -30,9 +30,9 @@ public class KeyDerivationTest extends BriarTestCase {
keys.add(crypto.deriveTagKey(secret, true));
keys.add(crypto.deriveTagKey(secret, false));
for(int i = 0; i < 4; i++) {
byte[] keyI = keys.get(i).getEncoded();
byte[] keyI = keys.get(i).getBytes();
for(int j = 0; j < 4; j++) {
byte[] keyJ = keys.get(j).getEncoded();
byte[] keyJ = keys.get(j).getBytes();
assertEquals(i == j, Arrays.equals(keyI, keyJ));
}
}
@@ -59,9 +59,8 @@ public class KeyDerivationTest extends BriarTestCase {
@Test
public void testStreamNumberAffectsDerivation() {
List<byte[]> secrets = new ArrayList<byte[]>();
for(int i = 0; i < 20; i++) {
secrets.add(crypto.deriveNextSecret(secret.clone(), i));
}
for(int i = 0; i < 20; i++)
secrets.add(crypto.deriveNextSecret(secret, i));
for(int i = 0; i < 20; i++) {
byte[] secretI = secrets.get(i);
for(int j = 0; j < 20; j++) {

View File

@@ -18,7 +18,7 @@ public class PasswordBasedKdfTest extends BriarTestCase {
Random random = new Random();
byte[] input = new byte[1234];
random.nextBytes(input);
char[] password = "password".toCharArray();
String password = "password";
byte[] ciphertext = crypto.encryptWithPassword(input, password);
byte[] output = crypto.decryptWithPassword(ciphertext, password);
assertArrayEquals(input, output);
@@ -29,7 +29,7 @@ public class PasswordBasedKdfTest extends BriarTestCase {
Random random = new Random();
byte[] input = new byte[1234];
random.nextBytes(input);
char[] password = "password".toCharArray();
String password = "password";
byte[] ciphertext = crypto.encryptWithPassword(input, password);
// Modify the ciphertext
int position = random.nextInt(ciphertext.length);

View File

@@ -6,24 +6,23 @@ import org.briarproject.BriarTestCase;
import org.briarproject.api.crypto.PasswordStrengthEstimator;
import org.junit.Test;
public class PasswordStrengthEstimatorTest extends BriarTestCase {
public class PasswordStrengthEstimatorImplTest extends BriarTestCase {
@Test
public void testWeakPasswords() {
PasswordStrengthEstimator e = new PasswordStrengthEstimatorImpl();
assertTrue(e.estimateStrength("".toCharArray()) < QUITE_STRONG);
assertTrue(e.estimateStrength("password".toCharArray()) < QUITE_STRONG);
assertTrue(e.estimateStrength("letmein".toCharArray()) < QUITE_STRONG);
assertTrue(e.estimateStrength("123456".toCharArray()) < QUITE_STRONG);
assertTrue(e.estimateStrength("") < QUITE_STRONG);
assertTrue(e.estimateStrength("password") < QUITE_STRONG);
assertTrue(e.estimateStrength("letmein") < QUITE_STRONG);
assertTrue(e.estimateStrength("123456") < QUITE_STRONG);
}
@Test
public void testStrongPasswords() {
PasswordStrengthEstimator e = new PasswordStrengthEstimatorImpl();
// Industry standard
assertTrue(e.estimateStrength("Tr0ub4dor&3".toCharArray())
> QUITE_STRONG);
assertTrue(e.estimateStrength("correcthorsebatterystaple".toCharArray())
assertTrue(e.estimateStrength("Tr0ub4dor&3") > QUITE_STRONG);
assertTrue(e.estimateStrength("correcthorsebatterystaple")
> QUITE_STRONG);
}
}

View File

@@ -1,27 +0,0 @@
package org.briarproject.crypto;
import static org.junit.Assert.assertArrayEquals;
import java.util.Random;
import org.briarproject.BriarTestCase;
import org.briarproject.api.crypto.SecretKey;
import org.junit.Test;
public class SecretKeyImplTest extends BriarTestCase {
private static final int KEY_BYTES = 32; // 256 bits
@Test
public void testCopiesAreErased() {
byte[] master = new byte[KEY_BYTES];
new Random().nextBytes(master);
SecretKey k = new SecretKeyImpl(master);
byte[] copy = k.getEncoded();
assertArrayEquals(master, copy);
k.erase();
byte[] blank = new byte[KEY_BYTES];
assertArrayEquals(blank, master);
assertArrayEquals(blank, copy);
}
}