KeyChainGroup: Fix NullPointerExceptions in decrypt() for the case of only a basic keychain.

This commit is contained in:
Matthew Leon
2019-03-28 21:04:43 -04:00
committed by Andreas Schildbach
parent 57d0eef454
commit f47badc76f
2 changed files with 12 additions and 8 deletions

View File

@@ -668,7 +668,6 @@ public class KeyChainGroup implements KeyBag {
checkNotNull(keyCrypter); checkNotNull(keyCrypter);
checkNotNull(aesKey); checkNotNull(aesKey);
checkState((chains != null && !chains.isEmpty()) || basic.numKeys() != 0, "can't encrypt entirely empty wallet"); checkState((chains != null && !chains.isEmpty()) || basic.numKeys() != 0, "can't encrypt entirely empty wallet");
// This code must be exception safe.
BasicKeyChain newBasic = basic.toEncrypted(keyCrypter, aesKey); BasicKeyChain newBasic = basic.toEncrypted(keyCrypter, aesKey);
List<DeterministicKeyChain> newChains = new ArrayList<>(); List<DeterministicKeyChain> newChains = new ArrayList<>();
@@ -676,6 +675,8 @@ public class KeyChainGroup implements KeyBag {
for (DeterministicKeyChain chain : chains) for (DeterministicKeyChain chain : chains)
newChains.add(chain.toEncrypted(keyCrypter, aesKey)); newChains.add(chain.toEncrypted(keyCrypter, aesKey));
} }
// Code below this point must be exception safe.
this.keyCrypter = keyCrypter; this.keyCrypter = keyCrypter;
this.basic = newBasic; this.basic = newBasic;
if (chains != null) { if (chains != null) {
@@ -691,18 +692,20 @@ public class KeyChainGroup implements KeyBag {
* @throws org.bitcoinj.crypto.KeyCrypterException Thrown if the wallet decryption fails for some reason, leaving the group unchanged. * @throws org.bitcoinj.crypto.KeyCrypterException Thrown if the wallet decryption fails for some reason, leaving the group unchanged.
*/ */
public void decrypt(KeyParameter aesKey) { public void decrypt(KeyParameter aesKey) {
// This code must be exception safe.
checkNotNull(aesKey); checkNotNull(aesKey);
BasicKeyChain newBasic = basic.toDecrypted(aesKey); BasicKeyChain newBasic = basic.toDecrypted(aesKey);
List<DeterministicKeyChain> newChains = new ArrayList<>(chains.size()); if (chains != null) {
if (chains != null) List<DeterministicKeyChain> newChains = new ArrayList<>(chains.size());
for (DeterministicKeyChain chain : chains) for (DeterministicKeyChain chain : chains)
newChains.add(chain.toDecrypted(aesKey)); newChains.add(chain.toDecrypted(aesKey));
// Code below this point must be exception safe.
this.chains.clear();
this.chains.addAll(newChains);
}
this.basic = newBasic;
this.keyCrypter = null; this.keyCrypter = null;
basic = newBasic;
chains.clear();
chains.addAll(newChains);
} }
/** Returns true if the group is encrypted. */ /** Returns true if the group is encrypted. */

View File

@@ -707,10 +707,11 @@ public class KeyChainGroupTest {
} }
@Test @Test
public void onlyBasicKeyEncryption() { public void onlyBasicKeyEncryptionAndDecryption() {
group = KeyChainGroup.createBasic(MAINNET); group = KeyChainGroup.createBasic(MAINNET);
final ECKey key = ECKey.fromPrivate(BigInteger.TEN); final ECKey key = ECKey.fromPrivate(BigInteger.TEN);
group.importKeys(key); group.importKeys(key);
group.encrypt(KEY_CRYPTER, AES_KEY); group.encrypt(KEY_CRYPTER, AES_KEY);
group.decrypt(AES_KEY);
} }
} }