Wallet: disallow adding of keys that don't match the wallet's encryption state.

This commit is contained in:
Mike Hearn
2014-03-17 16:30:57 +01:00
parent 22f5e45811
commit a49f643cdc
2 changed files with 26 additions and 30 deletions

View File

@@ -2065,10 +2065,10 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
// If the key has a keyCrypter that does not match the Wallet's then a KeyCrypterException is thrown.
// This is done because only one keyCrypter is persisted per Wallet and hence all the keys must be homogenous.
if (keyCrypter != null && keyCrypter.getUnderstoodEncryptionType() != EncryptionType.UNENCRYPTED) {
if (key.isEncrypted() && !keyCrypter.equals(key.getKeyCrypter())) {
throw new KeyCrypterException("Cannot add key " + key.toString() + " because the keyCrypter does not match the wallets. Keys must be homogenous.");
}
if (isEncrypted() && (!key.isEncrypted() || !keyCrypter.equals(key.getKeyCrypter()))) {
throw new KeyCrypterException("Cannot add key " + key.toString() + " because the keyCrypter does not match the wallets. Keys must be homogenous.");
} else if (key.isEncrypted() && !isEncrypted()) {
throw new KeyCrypterException("Cannot add key because it's encrypted and this wallet is not.");
}
keychain.add(key);
added++;

View File

@@ -68,8 +68,6 @@ public class WalletTest extends TestWithWallet {
private Address myEncryptedAddress2;
private Wallet encryptedWallet;
// A wallet with an initial unencrypted private key and an encrypted private key.
private Wallet encryptedMixedWallet;
private static CharSequence PASSWORD1 = "my helicopter contains eels";
private static CharSequence WRONG_PASSWORD = "nothing noone nobody nowhere";
@@ -90,16 +88,11 @@ public class WalletTest extends TestWithWallet {
keyCrypter = new KeyCrypterScrypt(scryptParameters);
encryptedWallet = new Wallet(params, keyCrypter);
encryptedMixedWallet = new Wallet(params, keyCrypter);
aesKey = keyCrypter.deriveKey(PASSWORD1);
wrongAesKey = keyCrypter.deriveKey(WRONG_PASSWORD);
ECKey myEncryptedKey = encryptedWallet.addNewEncryptedKey(keyCrypter, aesKey);
myEncryptedAddress = myEncryptedKey.toAddress(params);
encryptedMixedWallet.addKey(new ECKey());
ECKey myEncryptedKey2 = encryptedMixedWallet.addNewEncryptedKey(keyCrypter, aesKey);
myEncryptedAddress2 = myEncryptedKey2.toAddress(params);
}
@After
@@ -124,11 +117,6 @@ public class WalletTest extends TestWithWallet {
basicSpendingCommon(encryptedWallet, myEncryptedAddress, new ECKey().toAddress(params), true);
}
@Test
public void basicSpendingWithEncryptedMixedWallet() throws Exception {
basicSpendingCommon(encryptedMixedWallet, myEncryptedAddress2, new ECKey().toAddress(params), true);
}
static class TestRiskAnalysis implements RiskAnalysis {
private final boolean risky;
@@ -1312,38 +1300,33 @@ public class WalletTest extends TestWithWallet {
@Test
public void encryptionDecryptionBasic() throws Exception {
encryptionDecryptionBasicCommon(encryptedWallet);
encryptionDecryptionBasicCommon(encryptedMixedWallet);
}
private void encryptionDecryptionBasicCommon(Wallet wallet) {
// Check the wallet is initially of WalletType ENCRYPTED.
assertTrue("Wallet is not an encrypted wallet", wallet.getEncryptionType() == EncryptionType.ENCRYPTED_SCRYPT_AES);
assertTrue("Wallet is not an encrypted wallet", encryptedWallet.getEncryptionType() == EncryptionType.ENCRYPTED_SCRYPT_AES);
// Correct password should decrypt first encrypted private key.
assertTrue("checkPassword result is wrong with correct password.2", wallet.checkPassword(PASSWORD1));
assertTrue("checkPassword result is wrong with correct password.2", encryptedWallet.checkPassword(PASSWORD1));
// Incorrect password should not decrypt first encrypted private key.
assertFalse("checkPassword result is wrong with incorrect password.3", wallet.checkPassword(WRONG_PASSWORD));
assertFalse("checkPassword result is wrong with incorrect password.3", encryptedWallet.checkPassword(WRONG_PASSWORD));
// Decrypt wallet.
assertTrue("The keyCrypter is missing but should not be", keyCrypter != null);
wallet.decrypt(aesKey);
encryptedWallet.decrypt(aesKey);
// Wallet should now be unencrypted.
assertTrue("Wallet is not an unencrypted wallet", wallet.getKeyCrypter() == null);
assertTrue("Wallet is not an unencrypted wallet", encryptedWallet.getKeyCrypter() == null);
// Correct password should not decrypt first encrypted private key as wallet is unencrypted.
assertTrue("checkPassword result is wrong with correct password", !wallet.checkPassword(PASSWORD1));
assertTrue("checkPassword result is wrong with correct password", !encryptedWallet.checkPassword(PASSWORD1));
// Incorrect password should not decrypt first encrypted private key as wallet is unencrypted.
assertTrue("checkPassword result is wrong with incorrect password", !wallet.checkPassword(WRONG_PASSWORD));
assertTrue("checkPassword result is wrong with incorrect password", !encryptedWallet.checkPassword(WRONG_PASSWORD));
// Encrypt wallet.
wallet.encrypt(keyCrypter, aesKey);
encryptedWallet.encrypt(keyCrypter, aesKey);
// Wallet should now be of type WalletType.ENCRYPTED_SCRYPT_AES.
assertTrue("Wallet is not an encrypted wallet", wallet.getEncryptionType() == EncryptionType.ENCRYPTED_SCRYPT_AES);
assertTrue("Wallet is not an encrypted wallet", encryptedWallet.getEncryptionType() == EncryptionType.ENCRYPTED_SCRYPT_AES);
}
@Test
@@ -1394,6 +1377,19 @@ public class WalletTest extends TestWithWallet {
assertTrue("Wallet is not an encrypted wallet.3", encryptedWallet.getEncryptionType() == EncryptionType.ENCRYPTED_SCRYPT_AES);
}
@Test(expected = KeyCrypterException.class)
public void addUnencryptedKeyToEncryptedWallet() throws Exception {
ECKey key1 = new ECKey();
encryptedWallet.addKey(key1);
}
@Test(expected = KeyCrypterException.class)
public void addEncryptedKeyToUnencryptedWallet() throws Exception {
ECKey key1 = new ECKey();
key1 = key1.encrypt(keyCrypter, keyCrypter.deriveKey("PASSWORD!"));
wallet.addKey(key1);
}
@Test
public void encryptionDecryptionHomogenousKeys() throws Exception {
// Check the wallet is currently encrypted