/** * Returns leaf keys issued by this chain (including lookahead zone but no lookahead threshold) */ public List<DeterministicKey> getActiveKeys() { ImmutableList.Builder<DeterministicKey> keys = ImmutableList.builder(); for (ECKey key : getKeys(true)) { DeterministicKey dKey = (DeterministicKey) key; if (isLeaf(dKey)) { if (dKey.getParent().equals(internalKey) && dKey.getChildNumber().num() >= issuedInternalKeys + lookaheadSize) continue; if (dKey.getParent().equals(externalKey) && dKey.getChildNumber().num() >= issuedExternalKeys + lookaheadSize) continue; keys.add(dKey); } } return keys.build(); }
@Override public SimpleHDKeyChain toDecrypted(KeyParameter aesKey) { checkState(getKeyCrypter() != null, "Key chain not encrypted"); checkState(rootKey.isEncrypted(), "Root key not encrypted"); DeterministicKey decKey = rootKey.decrypt(getKeyCrypter(), aesKey); SimpleHDKeyChain chain = new SimpleHDKeyChain(decKey); // Now double check that the keys match to catch the case where the key is wrong but padding didn't catch it. if (!chain.getWatchingKey().getPubKeyPoint().equals(getWatchingKey().getPubKeyPoint())) throw new KeyCrypterException("Provided AES key is wrong"); chain.lookaheadSize = lookaheadSize; // Now copy the (pubkey only) leaf keys across to avoid rederiving them. The private key bytes are missing // anyway so there's nothing to decrypt. for (ECKey eckey : simpleKeyChain.getKeys()) { DeterministicKey key = (DeterministicKey) eckey; if (!isLeaf(key)) continue; // Not a leaf key. checkState(key.isEncrypted(), "Key is not encrypted"); DeterministicKey parent = chain.hierarchy.get(checkNotNull(key.getParent(), "Key has null parent").getPath(), false, false); // Clone the key to the new decrypted hierarchy. key = new DeterministicKey(key.getPubOnly(), parent); chain.hierarchy.putKey(key); chain.simpleKeyChain.importKeys(key); } chain.issuedExternalKeys = issuedExternalKeys; chain.issuedInternalKeys = issuedInternalKeys; return chain; }
private SimpleHDKeyChain(KeyCrypter crypter, KeyParameter aesKey, SimpleHDKeyChain chain) { checkArgument(!chain.rootKey.isEncrypted(), "Chain already encrypted"); this.issuedExternalKeys = chain.issuedExternalKeys; this.issuedInternalKeys = chain.issuedInternalKeys; this.lookaheadSize = chain.lookaheadSize; this.lookaheadThreshold = chain.lookaheadThreshold; simpleKeyChain = new SimpleKeyChain(crypter); // The first number is the "account number" but we don't use that feature. rootKey = chain.rootKey.encrypt(crypter, aesKey, null); hierarchy = new DeterministicHierarchy(rootKey); simpleKeyChain.importKey(rootKey); externalKey = encryptNonLeaf(aesKey, chain, rootKey, EXTERNAL_PATH); internalKey = encryptNonLeaf(aesKey, chain, rootKey, INTERNAL_PATH); // Now copy the (pubkey only) leaf keys across to avoid rederiving them. The private key bytes are missing // anyway so there's nothing to encrypt. for (ECKey eckey : chain.simpleKeyChain.getKeys()) { DeterministicKey key = (DeterministicKey) eckey; if (!isLeaf(key)) continue; // Not a leaf key. DeterministicKey parent = hierarchy.get(checkNotNull(key.getParent(), "Key has no parent").getPath(), false, false); // Clone the key to the new encrypted hierarchy. key = new DeterministicKey(key.getPubOnly(), parent); hierarchy.putKey(key); simpleKeyChain.importKey(key); } }