mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 21:59:54 +01:00
Re-encrypt the DB key with the stored key.
This commit is contained in:
@@ -153,6 +153,13 @@ public interface CryptoComponent {
|
|||||||
byte[] decryptWithPassword(byte[] ciphertext, String password,
|
byte[] decryptWithPassword(byte[] ciphertext, String password,
|
||||||
@Nullable KeyStoreConfig keyStoreConfig);
|
@Nullable KeyStoreConfig keyStoreConfig);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given ciphertext was encrypted using a stored key
|
||||||
|
* to strengthen the password-based key. The validity of the ciphertext is
|
||||||
|
* not checked.
|
||||||
|
*/
|
||||||
|
boolean isEncryptedWithStoredKey(byte[] ciphertext);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypts the given plaintext to the given public key.
|
* Encrypts the given plaintext to the given public key.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.briarproject.bramble.account;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.account.AccountManager;
|
import org.briarproject.bramble.api.account.AccountManager;
|
||||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
|
import org.briarproject.bramble.api.crypto.KeyStoreConfig;
|
||||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||||
import org.briarproject.bramble.api.identity.Identity;
|
import org.briarproject.bramble.api.identity.Identity;
|
||||||
@@ -210,13 +211,22 @@ class AccountManagerImpl implements AccountManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
byte[] ciphertext = fromHexString(hex);
|
byte[] ciphertext = fromHexString(hex);
|
||||||
|
KeyStoreConfig keyStoreConfig = databaseConfig.getKeyStoreConfig();
|
||||||
byte[] plaintext = crypto.decryptWithPassword(ciphertext, password,
|
byte[] plaintext = crypto.decryptWithPassword(ciphertext, password,
|
||||||
databaseConfig.getKeyStoreConfig());
|
keyStoreConfig);
|
||||||
if (plaintext == null) {
|
if (plaintext == null) {
|
||||||
LOG.info("Failed to decrypt database key");
|
LOG.info("Failed to decrypt database key");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new SecretKey(plaintext);
|
SecretKey key = new SecretKey(plaintext);
|
||||||
|
// If the DB key was encrypted without using a stored key and a stored
|
||||||
|
// key is now available, re-encrypt the DB key with the stored key
|
||||||
|
if (keyStoreConfig != null &&
|
||||||
|
!crypto.isEncryptedWithStoredKey(ciphertext)) {
|
||||||
|
LOG.info("Re-encrypting database key with stored key");
|
||||||
|
encryptAndStoreDatabaseKey(key, password);
|
||||||
|
}
|
||||||
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -467,6 +467,12 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEncryptedWithStoredKey(byte[] ciphertext) {
|
||||||
|
return ciphertext.length > 0 &&
|
||||||
|
ciphertext[0] == PBKDF_FORMAT_SCRYPT_KEYSTORE;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] encryptToKey(PublicKey publicKey, byte[] plaintext) {
|
public byte[] encryptToKey(PublicKey publicKey, byte[] plaintext) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -118,6 +118,8 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
|
|||||||
oneOf(crypto).decryptWithPassword(encryptedKey, password,
|
oneOf(crypto).decryptWithPassword(encryptedKey, password,
|
||||||
keyStoreConfig);
|
keyStoreConfig);
|
||||||
will(returnValue(key.getBytes()));
|
will(returnValue(key.getBytes()));
|
||||||
|
oneOf(crypto).isEncryptedWithStoredKey(encryptedKey);
|
||||||
|
will(returnValue(true));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
storeDatabaseKey(keyFile, encryptedKeyHex);
|
storeDatabaseKey(keyFile, encryptedKeyHex);
|
||||||
@@ -136,6 +138,35 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
|
|||||||
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSignInReEncryptsKey() throws Exception {
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(crypto).decryptWithPassword(encryptedKey, password,
|
||||||
|
keyStoreConfig);
|
||||||
|
will(returnValue(key.getBytes()));
|
||||||
|
oneOf(crypto).isEncryptedWithStoredKey(encryptedKey);
|
||||||
|
will(returnValue(false));
|
||||||
|
oneOf(crypto).encryptWithPassword(key.getBytes(), password,
|
||||||
|
keyStoreConfig);
|
||||||
|
will(returnValue(newEncryptedKey));
|
||||||
|
}});
|
||||||
|
|
||||||
|
storeDatabaseKey(keyFile, encryptedKeyHex);
|
||||||
|
storeDatabaseKey(keyBackupFile, encryptedKeyHex);
|
||||||
|
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
|
||||||
|
assertTrue(accountManager.signIn(password));
|
||||||
|
assertTrue(accountManager.hasDatabaseKey());
|
||||||
|
SecretKey decrypted = accountManager.getDatabaseKey();
|
||||||
|
assertNotNull(decrypted);
|
||||||
|
assertArrayEquals(key.getBytes(), decrypted.getBytes());
|
||||||
|
|
||||||
|
assertEquals(newEncryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(newEncryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDbKeyIsLoadedFromPrimaryFile() throws Exception {
|
public void testDbKeyIsLoadedFromPrimaryFile() throws Exception {
|
||||||
storeDatabaseKey(keyFile, encryptedKeyHex);
|
storeDatabaseKey(keyFile, encryptedKeyHex);
|
||||||
@@ -316,6 +347,8 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
|
|||||||
oneOf(crypto).decryptWithPassword(encryptedKey, password,
|
oneOf(crypto).decryptWithPassword(encryptedKey, password,
|
||||||
keyStoreConfig);
|
keyStoreConfig);
|
||||||
will(returnValue(key.getBytes()));
|
will(returnValue(key.getBytes()));
|
||||||
|
oneOf(crypto).isEncryptedWithStoredKey(encryptedKey);
|
||||||
|
will(returnValue(true));
|
||||||
oneOf(crypto).encryptWithPassword(key.getBytes(), newPassword,
|
oneOf(crypto).encryptWithPassword(key.getBytes(), newPassword,
|
||||||
keyStoreConfig);
|
keyStoreConfig);
|
||||||
will(returnValue(newEncryptedKey));
|
will(returnValue(newEncryptedKey));
|
||||||
|
|||||||
Reference in New Issue
Block a user