public final void decodePrivateKey(final BIP38PrivateKey encryptedKey, final String passphrase) { backgroundHandler.post(new Runnable() { @Override public void run() { try { final ECKey decryptedKey = encryptedKey.decrypt(passphrase); // takes time callbackHandler.post(new Runnable() { @Override public void run() { onSuccess(decryptedKey); } }); } catch (final BIP38PrivateKey.BadPassphraseException x) { callbackHandler.post(new Runnable() { @Override public void run() { onBadPassphrase(); } }); } } }); }
/** * * @return */ @Override public Map<String, String> getAddressesKeys() { Map<String, String> addrKeysMap = new HashMap<>(); List<ECKey> allWalletKeys = _coin.getWalletManager().wallet().getImportedKeys(); allWalletKeys.addAll(_coin.getWalletManager().wallet().getIssuedReceiveKeys()); for (ECKey k : allWalletKeys) { Address addr = k.toAddress(Constants.NETWORK_PARAMETERS); String hash = WalletUtils.formatAddress(addr, Constants.ADDRESS_FORMAT_GROUP_SIZE, Constants.ADDRESS_FORMAT_LINE_SIZE).toString(); addrKeysMap.put(hash, k.getPrivateKeyAsHex()); } return addrKeysMap; }
CLTVScriptPair(ECKey newPsynymKey, long expireDate) { ScriptBuilder sb = new ScriptBuilder(); //the part that freezes the tx output, special 5 byte number sb.data(encodeExpireDate(expireDate)); //sb.smallNum(num) sb.op(ScriptOpCodes.OP_CHECKLOCKTIMEVERIFY); sb.op(ScriptOpCodes.OP_DROP); //standard p2pkh part sb.op(ScriptOpCodes.OP_DUP); sb.op(ScriptOpCodes.OP_HASH160); sb.data(newPsynymKey.getPubKeyHash()); sb.op(ScriptOpCodes.OP_EQUALVERIFY); sb.op(ScriptOpCodes.OP_CHECKSIG); this.redeemScript = sb.build(); System.out.println("cltvscripiar yielded a locktime of " + new Date(getLockTime()*1000)); assert(expireDate == getLockTime()); this.pubKeyScript = ScriptBuilder.createP2SHOutputScript(redeemScript); this.pubkeyHash = newPsynymKey.getPubKeyHash(); this.pubkey = newPsynymKey.getPubKey(); }
/** Returns the first ECKey created after the given UNIX time, or null if there is none. */ @Nullable public ECKey findOldestKeyAfter(long timeSecs) { lock.lock(); try { ECKey oldest = null; for (ECKey key : hashToKeys.values()) { final long keyTime = key.getCreationTimeSeconds(); if (keyTime > timeSecs) { if (oldest == null || oldest.getCreationTimeSeconds() > keyTime) oldest = key; } } return oldest; } finally { lock.unlock(); } }
/** * Returns a decoded signature. * * @param requireCanonicalEncoding if the encoding of the signature must * be canonical. * @param requireCanonicalSValue if the S-value must be canonical (below half * the order of the curve). * @throws RuntimeException if the signature is invalid or unparseable in some way. */ public static TransactionSignature decodeFromBitcoin(byte[] bytes, boolean requireCanonicalEncoding, boolean requireCanonicalSValue) throws VerificationException { // Bitcoin encoding is DER signature + sighash byte. if (requireCanonicalEncoding && !isEncodingCanonical(bytes)) throw new VerificationException("Signature encoding is not canonical."); ECKey.ECDSASignature sig; try { sig = ECKey.ECDSASignature.decodeFromDER(bytes); } catch (IllegalArgumentException e) { throw new VerificationException("Could not decode DER", e); } if (requireCanonicalSValue && !sig.isCanonical()) throw new VerificationException("S-value is not canonical."); // In Bitcoin, any value of the final byte is valid, but not necessarily canonical. See javadocs for // isEncodingCanonical to learn more about this. So we must store the exact byte found. return new TransactionSignature(sig.r, sig.s, bytes[bytes.length - 1]); }
private int estimateBytesForSigning(CoinSelection selection) { int size = 0; for (TransactionOutput output : selection.gathered) { try { Script script = output.getScriptPubKey(); ECKey key = null; Script redeemScript = null; if (script.isSentToAddress()) { key = findKeyFromPubHash(script.getPubKeyHash()); checkNotNull(key, "Coin selection includes unspendable outputs"); } else if (script.isPayToScriptHash()) { redeemScript = findRedeemDataFromScriptHash(script.getPubKeyHash()).redeemScript; checkNotNull(redeemScript, "Coin selection includes unspendable outputs"); } size += script.getNumberOfBytesRequiredToSpend(key, redeemScript); } catch (ScriptException e) { // If this happens it means an output script in a wallet tx could not be understood. That should never // happen, if it does it means the wallet has got into an inconsistent state. throw new IllegalStateException(e); } } return size; }
/** Checks if the given input passes some of the AreInputsStandard checks. Not complete. */ public static RuleViolation isInputStandard(TransactionInput input) { for (ScriptChunk chunk : input.getScriptSig().getChunks()) { if (chunk.data != null && !chunk.isShortestPossiblePushData()) return RuleViolation.SHORTEST_POSSIBLE_PUSHDATA; if (chunk.isPushData()) { ECDSASignature signature; try { signature = ECKey.ECDSASignature.decodeFromDER(chunk.data); } catch (IllegalArgumentException x) { // Doesn't look like a signature. signature = null; } if (signature != null) { if (!TransactionSignature.isEncodingCanonical(chunk.data)) return RuleViolation.SIGNATURE_CANONICAL_ENCODING; if (!signature.isCanonical()) return RuleViolation.SIGNATURE_CANONICAL_ENCODING; } } } return RuleViolation.NONE; }
List<ECKey> getKeys(boolean includeLookahead, boolean includeParents) { List<ECKey> keys = basicKeyChain.getKeys(); if (!includeLookahead) { int treeSize = internalParentKey.getPath().size(); List<ECKey> issuedKeys = new LinkedList<>(); for (ECKey key : keys) { DeterministicKey detkey = (DeterministicKey) key; DeterministicKey parent = detkey.getParent(); if (!includeParents && parent == null) continue; if (!includeParents && detkey.getPath().size() <= treeSize) continue; if (internalParentKey.equals(parent) && detkey.getChildNumber().i() >= issuedInternalKeys) continue; if (externalParentKey.equals(parent) && detkey.getChildNumber().i() >= issuedExternalKeys) continue; issuedKeys.add(detkey); } return issuedKeys; } return keys; }
@Override public BasicKeyChain toDecrypted(KeyParameter aesKey) { lock.lock(); try { checkState(keyCrypter != null, "Wallet is already decrypted"); // Do an up-front check. if (numKeys() > 0 && !checkAESKey(aesKey)) throw new KeyCrypterException("Password/key was incorrect."); BasicKeyChain decrypted = new BasicKeyChain(); for (ECKey key : hashToKeys.values()) { decrypted.importKeyLocked(key.decrypt(aesKey)); } return decrypted; } finally { lock.unlock(); } }
/** Returns a list of all ECKeys created after the given UNIX time. */ public List<ECKey> findKeysBefore(long timeSecs) { lock.lock(); try { List<ECKey> results = Lists.newLinkedList(); for (ECKey key : hashToKeys.values()) { final long keyTime = key.getCreationTimeSeconds(); if (keyTime < timeSecs) { results.add(key); } } return results; } finally { lock.unlock(); } }
/** * Encrypt the wallet using the KeyCrypter and the AES key. A good default KeyCrypter to use is * {@link org.bitcoinj.crypto.KeyCrypterScrypt}. * * @param keyCrypter The KeyCrypter that specifies how to encrypt/ decrypt a key * @param aesKey AES key to use (normally created using KeyCrypter#deriveKey and cached as it is time consuming * to create from a password) * @throws KeyCrypterException Thrown if the wallet encryption fails. If so, the wallet state is unchanged. */ @Override public BasicKeyChain toEncrypted(KeyCrypter keyCrypter, KeyParameter aesKey) { lock.lock(); try { checkNotNull(keyCrypter); checkState(this.keyCrypter == null, "Key chain is already encrypted"); BasicKeyChain encrypted = new BasicKeyChain(keyCrypter); for (ECKey key : hashToKeys.values()) { ECKey encryptedKey = key.encrypt(keyCrypter, aesKey); // Check that the encrypted key can be successfully decrypted. // This is done as it is a critical failure if the private key cannot be decrypted successfully // (all bitcoin controlled by that private key is lost forever). // For a correctly constructed keyCrypter the encryption should always be reversible so it is just // being as cautious as possible. if (!ECKey.encryptionIsReversible(key, encryptedKey, keyCrypter, aesKey)) throw new KeyCrypterException("The key " + key.toString() + " cannot be successfully decrypted after encryption so aborting wallet encryption."); encrypted.importKeyLocked(encryptedKey); } return encrypted; } finally { lock.unlock(); } }
public Optional<String> getToken() { final ListenableFuture<String> masterPassword = encyptionKeyProvider.getMasterPassword(); if (!masterPassword.isDone()) { return Optional.empty(); } final String key = encyptionKeyProvider.getImmediatePassword(); final String s = key + " meta"; final ECKey privKey = ECKey.fromPrivate(Sha256Hash.twiceOf(s.getBytes(Charsets.UTF_8)).getBytes()); /* @POST @Path("/token") @Produces(MediaType.APPLICATION_OCTET_STREAM) public Response createToken(@QueryParam("timestamp") Long nonce, @QueryParam("signature") String signature) { */ // } final long timeStamp = Instant.now().toEpochMilli(); try { final String url = rootPath + "auth/token"; final HttpResponse<String> token = Unirest.post(url) .queryString("timestamp", timeStamp) .queryString("signature", privKey.signMessage(String.valueOf(timeStamp))) .asString(); if (token.getStatus() != 200) { return Optional.empty(); } return Optional.of(token.getBody()); } catch (UnirestException e) { LOGGER.error("exception from remote service when trying to get token", e); return Optional.empty(); } }
public boolean isValidEthereumAddress(String address) { try { org.ethereum.crypto.ECKey.fromPublicOnly(Hex.decode(address.replace("0x", ""))); return true; } catch (Throwable e) { return false; } }
public Keys getKeys() { ECKey key = new ECKey(); byte[] address = key.getPubKey(); String addressAsString = key.toAddress(getNetworkParameters()).toString(); byte[] privateKey = key.getPrivKeyBytes(); String addressAsStringWithPrivate = key.toStringWithPrivate(getNetworkParameters()).toString(); return new Keys() .setAddress(address) .setAddressAsString(addressAsString) .setPrivateKey(privateKey) .setAddressAsStringWithPrivate(addressAsStringWithPrivate); }
@Override public String get() { synchronized (lock) { ECKey ecKey = ECKey.fromPrivate(startPrivateKey); String privateKeyToCheck = ecKey.getPrivateKeyAsWiF(Constants.NETWORK_PARAMS); startPrivateKey = startPrivateKey.add(BigInteger.ONE); keyCount = keyCount.add(BigInteger.ONE); logKeyRate(); return privateKeyToCheck; } }
/** * Imports a key to the key chain. If key is present in the key chain, ignore it. */ public void importKey(ECKey key) { lock.lock(); try { checkKeyEncryptionStateMatches(key); if (hasKey(key)) return; importKeyLocked(key); queueOnKeysAdded(ImmutableList.of(key)); } finally { lock.unlock(); } }
private void askConfirmSweep(final ECKey key) { // create non-HD wallet final KeyChainGroup group = new KeyChainGroup(Constants.NETWORK_PARAMETERS); group.importKeys(key); walletToSweep = new Wallet(Constants.NETWORK_PARAMETERS, group); setState(State.CONFIRM_SWEEP); // delay until fragment is resumed handler.post(requestWalletBalanceRunnable); }
@Override public BloomFilter getFilter(int size, double falsePositiveRate, long tweak) { lock.lock(); try { BloomFilter filter = new BloomFilter(size, falsePositiveRate, tweak); for (ECKey key : hashToKeys.values()) filter.insert(key); return filter; } finally { lock.unlock(); } }
/** * */ private void initWallet(final NetworkParameters netParams) { //File dataDir = getDir("consensus_folder", Context.MODE_PRIVATE); // _bitcoinJContext = new org.bitcoinj.core.Context(netParams); // Start up a basic app using a class that automates some boilerplate. Ensure we always have at least one key. _walletKit = new WalletAppKit(Constants.NETWORK_PARAMETERS, _bitcoin.getDataDir(), ServiceConsts.SERVICE_APP_NAME + "-" + netParams.getPaymentProtocolId()) { /** * */ @Override protected void onSetupCompleted() { System.out.println("Setting up wallet : " + wallet().toString()); // This is called in a background thread after startAndWait is called, as setting up various objects // can do disk and network IO that may cause UI jank/stuttering in wallet apps if it were to be done // on the main thread. if (wallet().getKeyChainGroupSize() < 1) wallet().importKey(new ECKey()); peerGroup().setFastCatchupTimeSecs(wallet().getEarliestKeyCreationTime()); peerGroup().addPeerDiscovery(new DnsDiscovery(netParams)); // wallet.removeCoinsReceivedEventListener(_bitcoinManger); // wallet.addCoinsReceivedEventListener(_bitcoinManger); _bitcoin.setWalletManager(_walletKit); } }; }
public static void writeKeys(final Writer out, final List<ECKey> keys) throws IOException { final DateFormat format = Iso8601Format.newDateTimeFormatT(); out.write("# KEEP YOUR PRIVATE KEYS SAFE! Anyone who can read this can spend your Bitcoins.\n"); for (final ECKey key : keys) { out.write(key.getPrivateKeyEncoded(Constants.NETWORK_PARAMETERS).toBase58()); if (key.getCreationTimeSeconds() != 0) { out.write(' '); out.write(format.format(new Date(key.getCreationTimeSeconds() * DateUtils.SECOND_IN_MILLIS))); } out.write('\n'); } }
/** * Constructor an HD address. * * @param NetworkParameters params * @param DeterministicKey cKey deterministic key for this address * @param int child index of this address in its chain * */ public Address(NetworkParameters params, DeterministicKey cKey, int child) { this.params = params; childNum = child; DeterministicKey dk = HDKeyDerivation.deriveChildKey(cKey, new ChildNumber(childNum, false)); // compressed WIF private key format if(dk.hasPrivKey()) { // byte[] prepended0Byte = ArrayUtils.addAll(new byte[1], dk.getPrivKeyBytes()); byte[] getPrivKeyBytes = dk.getPrivKeyBytes(); byte[] prepended0Byte = new byte[1 + getPrivKeyBytes.length]; prepended0Byte[0] = 0; System.arraycopy(getPrivKeyBytes, 0, prepended0Byte, 1, getPrivKeyBytes.length); ecKey = ECKey.fromPrivate(new BigInteger(prepended0Byte), true); } else { ecKey = ECKey.fromPublicOnly(dk.getPubKey()); } long now = Utils.now().getTime() / 1000; // use Unix time (in seconds) ecKey.setCreationTimeSeconds(now); pubKey = ecKey.getPubKey(); pubKeyHash = ecKey.getPubKeyHash(); strPath = dk.getPathAsString(); }
public void sendBroadcastAnnouncement(BroadcastAnnouncement ba, File f, ProofMessage pm, int lockTime) throws InsufficientMoneyException { //build transaction Transaction tx = new Transaction(params); Script s = ba.buildScript(); System.out.println("Script size is " + s.SIG_SIZE); //System.out.println(s.getScriptType()); ECKey psnymKey = new ECKey(); long unixTime = System.currentTimeMillis() / 1000L; //TODO use bitcoin nets median time tx.setLockTime(CLTVScriptPair.currentBitcoinBIP113Time(bc)-1); CLTVScriptPair sp = new CLTVScriptPair(psnymKey, CLTVScriptPair.currentBitcoinBIP113Time(bc)+lockTime); w.importKey(psnymKey); tx.addOutput(new TransactionOutput(params, tx, pm.getLastTransactionOutput().getValue().subtract(estimateBroadcastFee()), sp.getPubKeyScript().getProgram())); tx.addOutput(Coin.ZERO, s); tx.addInput(pm.getLastTransactionOutput()); tx.getInput(0).setSequenceNumber(3); //the concrete value doesn't matter, this is just for cltv tx.getInput(0).setScriptSig(pm.getScriptPair().calculateSigScript(tx, 0, w)); try { w.commitTx(tx); w.saveToFile(f); } catch (IOException e1) { e1.printStackTrace(); } TransactionBroadcast broadcast = pg.broadcastTransaction(tx); pm.addTransaction(tx, 0, sp); pm.writeToFile(); System.out.println("save broadcast announcement to file"); }
private static List<ECKey> extractAllValidKeys(List<String> allValids, List<ECKey> keys) { ArrayList<ECKey> valids = new ArrayList<ECKey>(); for (String valid : allValids) { for (ECKey keypair : keys) { if (keypair.toAddress(MainNetParams.get()).toBase58().equals(valid)) { valids.add(keypair); } } } return valids; }
public ECKey findKeyFromPubKey(byte[] pubkey) { lock.lock(); try { return pubkeyToKeys.get(ByteString.copyFrom(pubkey)); } finally { lock.unlock(); } }
/** * Removes the given key from the keychain. Be very careful with this - losing a private key <b>destroys the * money associated with it</b>. * @return Whether the key was removed or not. */ public boolean removeKey(ECKey key) { lock.lock(); try { boolean a = hashToKeys.remove(ByteString.copyFrom(key.getPubKeyHash())) != null; boolean b = pubkeyToKeys.remove(ByteString.copyFrom(key.getPubKey())) != null; checkState(a == b); // Should be in both maps or neither. return a; } finally { lock.unlock(); } }
/** * Returns only the keys that have been issued by {@link #freshReceiveKey()}, {@link #freshReceiveAddress()}, * {@link #currentReceiveKey()} or {@link #currentReceiveAddress()}. */ public List<ECKey> getIssuedReceiveKeys() { keyChainGroupLock.lock(); try { return keyChainGroup.getActiveKeyChain().getIssuedReceiveKeys(); } finally { keyChainGroupLock.unlock(); } }
private void importKeyLocked(ECKey key) { if (hashToKeys.isEmpty()) { isWatching = key.isWatching(); } else { if (key.isWatching() && !isWatching) throw new IllegalArgumentException("Key is watching but chain is not"); if (!key.isWatching() && isWatching) throw new IllegalArgumentException("Key is not watching but chain is"); } ECKey previousKey = pubkeyToKeys.put(ByteString.copyFrom(key.getPubKey()), key); hashToKeys.put(ByteString.copyFrom(key.getPubKeyHash()), key); checkState(previousKey == null); }
/** * Removes the given key from the basicKeyChain. Be very careful with this - losing a private key <b>destroys the * money associated with it</b>. * @return Whether the key was removed or not. */ public boolean removeKey(ECKey key) { keyChainGroupLock.lock(); try { return keyChainGroup.removeImportedKey(key); } finally { keyChainGroupLock.unlock(); } }
/** * Returns a list of the non-deterministic keys that have been imported into the wallet, or the empty list if none. */ public List<ECKey> getImportedKeys() { keyChainGroupLock.lock(); try { return keyChainGroup.getImportedKeys(); } finally { keyChainGroupLock.unlock(); } }
/** * Imports the given keys to the wallet. * If {@link Wallet#autosaveToFile(java.io.File, long, java.util.concurrent.TimeUnit, org.bitcoinj.wallet.WalletFiles.Listener)} * has been called, triggers an auto save bypassing the normal coalescing delay and event handlers. * Returns the number of keys added, after duplicates are ignored. The onKeyAdded event will be called for each key * in the list that was not already present. */ public int importKeys(final List<ECKey> keys) { // API usage check. checkNoDeterministicKeys(keys); int result; keyChainGroupLock.lock(); try { result = keyChainGroup.importKeys(keys); } finally { keyChainGroupLock.unlock(); } saveNow(); return result; }
/** Takes a list of keys and a password, then encrypts and imports them in one step using the current keycrypter. */ public int importKeysAndEncrypt(final List<ECKey> keys, CharSequence password) { keyChainGroupLock.lock(); try { checkNotNull(getKeyCrypter(), "Wallet is not encrypted"); return importKeysAndEncrypt(keys, getKeyCrypter().deriveKey(password)); } finally { keyChainGroupLock.unlock(); } }
Map<ECKey, Protos.Key.Builder> serializeToEditableProtobufs() { Map<ECKey, Protos.Key.Builder> result = new LinkedHashMap<>(); for (ECKey ecKey : hashToKeys.values()) { Protos.Key.Builder protoKey = serializeEncryptableItem(ecKey); protoKey.setPublicKey(ByteString.copyFrom(ecKey.getPubKey())); result.put(ecKey, protoKey); } return result; }
/** * Locates a keypair from the basicKeyChain given the hash of the public key. This is needed when finding out which * key we need to use to redeem a transaction output. * * @return ECKey object or null if no such key was found. */ @Override @Nullable public ECKey findKeyFromPubHash(byte[] pubkeyHash) { keyChainGroupLock.lock(); try { return keyChainGroup.findKeyFromPubHash(pubkeyHash); } finally { keyChainGroupLock.unlock(); } }
/** Returns true if the given key is in the wallet, false otherwise. Currently an O(N) operation. */ public boolean hasKey(ECKey key) { keyChainGroupLock.lock(); try { return keyChainGroup.hasKey(key); } finally { keyChainGroupLock.unlock(); } }
/** * Locates a keypair from the basicKeyChain given the raw public key bytes. * @return ECKey or null if no such key was found. */ @Override @Nullable public ECKey findKeyFromPubKey(byte[] pubkey) { keyChainGroupLock.lock(); try { return keyChainGroup.findKeyFromPubKey(pubkey); } finally { keyChainGroupLock.unlock(); } }
/** * Returns the immutable seed for the current active HD chain. * @throws org.bitcoinj.core.ECKey.MissingPrivateKeyException if the seed is unavailable (watching wallet) */ public DeterministicSeed getKeyChainSeed() { keyChainGroupLock.lock(); try { DeterministicSeed seed = keyChainGroup.getActiveKeyChain().getSeed(); if (seed == null) throw new ECKey.MissingPrivateKeyException(); return seed; } finally { keyChainGroupLock.unlock(); } }
/** Create a new married key and return the matching output script */ @Override public Script freshOutputScript(KeyPurpose purpose) { DeterministicKey followedKey = getKey(purpose); ImmutableList.Builder<ECKey> keys = ImmutableList.<ECKey>builder().add(followedKey); for (DeterministicKeyChain keyChain : followingKeyChains) { DeterministicKey followingKey = keyChain.getKey(purpose); checkState(followedKey.getChildNumber().equals(followingKey.getChildNumber()), "Following keychains should be in sync"); keys.add(followingKey); } List<ECKey> marriedKeys = keys.build(); Script redeemScript = ScriptBuilder.createRedeemScript(sigsRequiredToSpend, marriedKeys); return ScriptBuilder.createP2SHOutputScript(redeemScript); }
/** Get the redeem data for a key in this married chain */ @Override public RedeemData getRedeemData(DeterministicKey followedKey) { List<ECKey> marriedKeys = getMarriedKeysWithFollowed(followedKey); Script redeemScript = ScriptBuilder.createRedeemScript(sigsRequiredToSpend, marriedKeys); return RedeemData.of(marriedKeys, redeemScript); }
/** * For use in encryption when {@link #toEncrypted(KeyCrypter, KeyParameter)} is called, so that * subclasses can override that method and create an instance of the right class. * * See also {@link #makeKeyChainFromSeed(DeterministicSeed)} */ protected DeterministicKeyChain(KeyCrypter crypter, KeyParameter aesKey, DeterministicKeyChain chain) { // Can't encrypt a watching chain. checkNotNull(chain.rootKey); checkNotNull(chain.seed); checkArgument(!chain.rootKey.isEncrypted(), "Chain already encrypted"); this.issuedExternalKeys = chain.issuedExternalKeys; this.issuedInternalKeys = chain.issuedInternalKeys; this.lookaheadSize = chain.lookaheadSize; this.lookaheadThreshold = chain.lookaheadThreshold; this.seed = chain.seed.encrypt(crypter, aesKey); basicKeyChain = new BasicKeyChain(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); basicKeyChain.importKey(rootKey); for (int i = 1; i < getAccountPath().size(); i++) { encryptNonLeaf(aesKey, chain, rootKey, getAccountPath().subList(0, i)); } DeterministicKey account = encryptNonLeaf(aesKey, chain, rootKey, getAccountPath()); externalParentKey = encryptNonLeaf(aesKey, chain, account, HDUtils.concat(getAccountPath(), EXTERNAL_SUBPATH)); internalParentKey = encryptNonLeaf(aesKey, chain, account, HDUtils.concat(getAccountPath(), INTERNAL_SUBPATH)); // 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.basicKeyChain.getKeys()) { DeterministicKey key = (DeterministicKey) eckey; if (key.getPath().size() != getAccountPath().size() + 2) continue; // Not a leaf key. DeterministicKey parent = hierarchy.get(checkNotNull(key.getParent()).getPath(), false, false); // Clone the key to the new encrypted hierarchy. key = new DeterministicKey(key.dropPrivateBytes(), parent); hierarchy.putKey(key); basicKeyChain.importKey(key); } }