public Wallet(List<String> mnemonic, @Nullable String password) throws MnemonicException { MnemonicCode.INSTANCE.check(mnemonic); password = password == null ? "" : password; seed = new DeterministicSeed(mnemonic, null, password, 0); masterKey = HDKeyDerivation.createMasterPrivateKey(seed.getSeedBytes()); accountsByType = new LinkedHashMap<CoinType, ArrayList<WalletAccount>>(); accounts = new LinkedHashMap<String, WalletAccount>(); }
/** * Constructor for wallet. * * @param mc mnemonic code object * @param seed seed for this wallet * @param passphrase optional BIP39 passphrase * @param nbAccounts number of accounts to create */ public HDWallet(MnemonicCode mc, NetworkParameters params, byte[] seed, String passphrase, int nbAccounts) throws MnemonicException.MnemonicLengthException { this.params = params; this.seed = seed; strPassphrase = passphrase; wordList = mc.toMnemonic(seed); byte[] hd_seed = MnemonicCode.toSeed(wordList, strPassphrase); dkKey = HDKeyDerivation.createMasterPrivateKey(hd_seed); DeterministicKey dKey = HDKeyDerivation.deriveChildKey(dkKey, 44 | ChildNumber.HARDENED_BIT); dkRoot = HDKeyDerivation.deriveChildKey(dKey, ChildNumber.HARDENED_BIT); accounts = new ArrayList<HDAccount>(); for (int i = 0; i < nbAccounts; i++) { accounts.add(new HDAccount(params, dkRoot, i)); } strPath = dKey.getPathAsString(); }
/** * @throws HDDerivationException if privKeyBytes is invalid (0 or >= n). */ public static DeterministicKey createMasterPrivKeyFromBytes(byte[] privKeyBytes, byte[] chainCode) throws HDDerivationException { // childNumberPath is an empty list because we are creating the root key. return createMasterPrivKeyFromBytes(privKeyBytes, chainCode, ImmutableList.<ChildNumber> of()); }
/** * @throws HDDerivationException if privKeyBytes is invalid (0 or >= n). */ public static DeterministicKey createMasterPrivKeyFromBytes(byte[] privKeyBytes, byte[] chainCode, ImmutableList<ChildNumber> childNumberPath) throws HDDerivationException { BigInteger priv = new BigInteger(1, privKeyBytes); assertNonZero(priv, "Generated master key is invalid."); assertLessThanN(priv, "Generated master key is invalid."); return new DeterministicKey(childNumberPath, chainCode, priv, null); }
public static DeterministicKey deriveHardened(DeterministicKey node, int type) { return HDKeyDerivation.deriveChildKey(node, type | ChildNumber.HARDENED_BIT); } }
@Test public void inverseEqualsNormal() throws Exception { DeterministicKey key1 = HDKeyDerivation.createMasterPrivateKey("Wired / Aug 13th 2014 / Snowden: I Left the NSA Clues, But They Couldn't Find Them".getBytes()); HDKeyDerivation.RawKeyBytes key2 = HDKeyDerivation.deriveChildKeyBytesFromPublic(key1.dropPrivateBytes().dropParent(), ChildNumber.ZERO, HDKeyDerivation.PublicDeriveMode.NORMAL); HDKeyDerivation.RawKeyBytes key3 = HDKeyDerivation.deriveChildKeyBytesFromPublic(key1.dropPrivateBytes().dropParent(), ChildNumber.ZERO, HDKeyDerivation.PublicDeriveMode.WITH_INVERSION); assertArrayEquals(key2.keyBytes, key3.keyBytes); assertArrayEquals(key2.chainCode, key3.chainCode); }
DeterministicKey ekprv = HDKeyDerivation.createMasterPrivKeyFromBytes(priv, chain); DeterministicKey ekprv_0 = HDKeyDerivation.deriveChildKey(ekprv, 0); DeterministicKey ekprv_1 = HDKeyDerivation.deriveChildKey(ekprv, 1); DeterministicKey ekprv_0_EX = HDKeyDerivation.deriveChildKey(ekprv_0, HDW_CHAIN_EXTERNAL); DeterministicKey ekprv_0_IN = HDKeyDerivation.deriveChildKey(ekprv_0, HDW_CHAIN_INTERNAL); DeterministicKey ekprv_0_EX_0 = HDKeyDerivation.deriveChildKey(ekprv_0_EX, 0); DeterministicKey ekprv_0_EX_1 = HDKeyDerivation.deriveChildKey(ekprv_0_EX, 1); DeterministicKey ekprv_0_EX_2 = HDKeyDerivation.deriveChildKey(ekprv_0_EX, 2); DeterministicKey ekprv_0_IN_0 = HDKeyDerivation.deriveChildKey(ekprv_0_IN, 0); DeterministicKey ekprv_0_IN_1 = HDKeyDerivation.deriveChildKey(ekprv_0_IN, 1); DeterministicKey ekprv_0_IN_2 = HDKeyDerivation.deriveChildKey(ekprv_0_IN, 2); DeterministicKey ekprv_1_IN = HDKeyDerivation.deriveChildKey(ekprv_1, HDW_CHAIN_INTERNAL); DeterministicKey ekprv_1_IN_4095 = HDKeyDerivation.deriveChildKey(ekprv_1_IN, 4095); DeterministicKey ekpub = HDKeyDerivation.createMasterPubKeyFromBytes(HDUtils.toCompressed(pub), chain); DeterministicKey ekpub_0 = HDKeyDerivation.deriveChildKey(ekpub, 0); DeterministicKey ekpub_1 = HDKeyDerivation.deriveChildKey(ekpub, 1); DeterministicKey ekpub_0_EX = HDKeyDerivation.deriveChildKey(ekpub_0, HDW_CHAIN_EXTERNAL); DeterministicKey ekpub_0_IN = HDKeyDerivation.deriveChildKey(ekpub_0, HDW_CHAIN_INTERNAL); DeterministicKey ekpub_0_EX_0 = HDKeyDerivation.deriveChildKey(ekpub_0_EX, 0); DeterministicKey ekpub_0_EX_1 = HDKeyDerivation.deriveChildKey(ekpub_0_EX, 1);
/** * @throws HDDerivationException if private derivation is attempted for a public-only parent key, or * if the resulting derived key is invalid (eg. private key == 0). */ public static DeterministicKey deriveChildKey(DeterministicKey parent, ChildNumber childNumber) throws HDDerivationException { if (!parent.hasPrivKey()) { RawKeyBytes rawKey = deriveChildKeyBytesFromPublic(parent, childNumber, PublicDeriveMode.NORMAL); return new DeterministicKey( HDUtils.append(parent.getPath(), childNumber), rawKey.chainCode, new LazyECPoint(ECKey.CURVE.getCurve(), rawKey.keyBytes), null, parent); } else { RawKeyBytes rawKey = deriveChildKeyBytesFromPrivate(parent, childNumber); return new DeterministicKey( HDUtils.append(parent.getPath(), childNumber), rawKey.chainCode, new BigInteger(1, rawKey.keyBytes), parent); } }
byte[] chainCode = Arrays.copyOfRange(i, 32, 64); BigInteger ilInt = new BigInteger(1, il); assertLessThanN(ilInt, "Illegal derived key: I_L >= n"); assertNonInfinity(Ki, "Illegal derived key: derived public key equals infinity."); return new RawKeyBytes(Ki.getEncoded(true), chainCode);
private void checkForBitFlip(DeterministicKey k) { DeterministicKey parent = checkNotNull(k.getParent()); byte[] rederived = HDKeyDerivation.deriveChildKeyBytesFromPublic(parent, k.getChildNumber(), HDKeyDerivation.PublicDeriveMode.WITH_INVERSION).keyBytes; byte[] actual = k.getPubKey(); if (!Arrays.equals(rederived, actual)) throw new IllegalStateException(String.format(Locale.US, "Bit-flip check failed: %s vs %s", Arrays.toString(rederived), Arrays.toString(actual))); }
/** * Pre-generate enough keys to reach the lookahead size, but only if there are more than the lookaheadThreshold to * be generated, so that the Bloom filter does not have to be regenerated that often. * * The returned mutable list of keys must be inserted into the basic key chain. */ private List<DeterministicKey> maybeLookAhead(DeterministicKey parent, int issued, int lookaheadSize, int lookaheadThreshold) { checkState(lock.isHeldByCurrentThread(), "Lock is held by another thread"); final int numChildren = hierarchy.getNumChildren(parent.getPath()); final int needed = issued + lookaheadSize + lookaheadThreshold - numChildren; if (needed <= lookaheadThreshold) return new ArrayList<DeterministicKey>(); log.info("{} keys needed for {} = {} issued + {} lookahead size + {} lookahead threshold - {} num children", needed, parent.getPathAsString(), issued, lookaheadSize, lookaheadThreshold, numChildren); List<DeterministicKey> result = new ArrayList<DeterministicKey>(needed); long now = System.currentTimeMillis(); int nextChild = numChildren; for (int i = 0; i < needed; i++) { DeterministicKey key = HDKeyDerivation.deriveThisOrNextChildKey(parent, nextChild); key = key.getPubOnly(); hierarchy.putKey(key); result.add(key); nextChild = key.getChildNumber().num() + 1; } log.info("Took {} msec", System.currentTimeMillis() - now); return result; }
public static ECKey deriveECKey(DeterministicKey masterKey, int accountIndex) { DeterministicKey purposeKey = HDKeyDerivation.deriveChildKey(masterKey, DERIVATION_PATH_PURPOSE | ChildNumber.HARDENED_BIT); DeterministicKey rootKey = HDKeyDerivation.deriveChildKey(purposeKey, DERIVATION_PATH_COIN | ChildNumber.HARDENED_BIT); DeterministicKey accountKey = HDKeyDerivation.deriveChildKey(rootKey, accountIndex | ChildNumber.HARDENED_BIT); DeterministicKey changeKey = HDKeyDerivation.deriveChildKey(accountKey, CHANGE_INDEX); DeterministicKey addressKey = HDKeyDerivation.deriveChildKey(changeKey, ADDRESS_INDEX); return ECKey.fromPrivate(addressKey.getPrivKeyBytes()); }
/** * @throws HDDerivationException if privKeyBytes is invalid (0 or >= n). */ public static DeterministicKey createMasterPrivKeyFromBytes(byte[] privKeyBytes, byte[] chainCode) throws HDDerivationException { BigInteger priv = new BigInteger(1, privKeyBytes); assertNonZero(priv, "Generated master key is invalid."); assertLessThanN(priv, "Generated master key is invalid."); return new DeterministicKey(ImmutableList.<ChildNumber>of(), chainCode, priv, null); }
/** * @throws HDDerivationException if private derivation is attempted for a public-only parent key, or * if the resulting derived key is invalid (eg. private key == 0). */ public static DeterministicKey deriveChildKey(DeterministicKey parent, ChildNumber childNumber) throws HDDerivationException { if (!parent.hasPrivKey()) { RawKeyBytes rawKey = deriveChildKeyBytesFromPublic(parent, childNumber, PublicDeriveMode.NORMAL); return new DeterministicKey( HDUtils.append(parent.getPath(), childNumber), rawKey.chainCode, new LazyECPoint(ECKey.CURVE.getCurve(), rawKey.keyBytes), null, parent); } else { RawKeyBytes rawKey = deriveChildKeyBytesFromPrivate(parent, childNumber); return new DeterministicKey( HDUtils.append(parent.getPath(), childNumber), rawKey.chainCode, new BigInteger(1, rawKey.keyBytes), parent); } }
byte[] chainCode = Arrays.copyOfRange(i, 32, 64); BigInteger ilInt = new BigInteger(1, il); assertLessThanN(ilInt, "Illegal derived key: I_L >= n"); assertNonInfinity(Ki, "Illegal derived key: derived public key equals infinity."); return new RawKeyBytes(Ki.getEncoded(true), chainCode);
private void checkForBitFlip(DeterministicKey k) { DeterministicKey parent = checkNotNull(k.getParent()); byte[] rederived = HDKeyDerivation.deriveChildKeyBytesFromPublic(parent, k.getChildNumber(), HDKeyDerivation.PublicDeriveMode.WITH_INVERSION).keyBytes; byte[] actual = k.getPubKey(); if (!Arrays.equals(rederived, actual)) throw new IllegalStateException(String.format(Locale.US, "Bit-flip check failed: %s vs %s", Arrays.toString(rederived), Arrays.toString(actual))); }
/** * Pre-generate enough keys to reach the lookahead size, but only if there are more than the lookaheadThreshold to * be generated, so that the Bloom filter does not have to be regenerated that often. * * The returned mutable list of keys must be inserted into the basic key chain. */ private List<DeterministicKey> maybeLookAhead(DeterministicKey parent, int issued, int lookaheadSize, int lookaheadThreshold) { checkState(lock.isHeldByCurrentThread()); final int numChildren = hierarchy.getNumChildren(parent.getPath()); final int needed = issued + lookaheadSize + lookaheadThreshold - numChildren; if (needed <= lookaheadThreshold) return new ArrayList<>(); log.info("{} keys needed for {} = {} issued + {} lookahead size + {} lookahead threshold - {} num children", needed, parent.getPathAsString(), issued, lookaheadSize, lookaheadThreshold, numChildren); List<DeterministicKey> result = new ArrayList<>(needed); final Stopwatch watch = Stopwatch.createStarted(); int nextChild = numChildren; for (int i = 0; i < needed; i++) { DeterministicKey key = HDKeyDerivation.deriveThisOrNextChildKey(parent, nextChild); key = key.dropPrivateBytes(); hierarchy.putKey(key); result.add(key); nextChild = key.getChildNumber().num() + 1; } watch.stop(); log.info("Took {}", watch); return result; }
public Wallet(List<String> mnemonic, @Nullable String password) throws MnemonicException { MnemonicCode.INSTANCE.check(mnemonic); password = password == null ? "" : password; seed = new DeterministicSeed(mnemonic, null, password, 0); masterKey = HDKeyDerivation.createMasterPrivateKey(seed.getSeedBytes()); accountsByType = new LinkedHashMap<CoinType, ArrayList<WalletAccount>>(); accounts = new LinkedHashMap<String, WalletAccount>(); }
DeterministicKey dkKey = HDKeyDerivation.createMasterPrivateKey(seedBytes); for (int i = 1; i < pathArray.length; i++) { ChildNumber childNumber; childNumber = new ChildNumber(number, false); dkKey = HDKeyDerivation.deriveChildKey(dkKey, childNumber);
/** * Generate the DeterministicKey from the private master key for a Trezor wallet * <p/> * For a real Trezor device this will be the result of a GetPublicKey of the M/44'/0'/0' path, received as an xpub and then converted to a DeterministicKey * * @param privateMasterKey the private master key derived from the wallet seed * * @return the public only DeterministicSeed corresponding to the root Trezor wallet node e.g. M/44'/0'/0' */ public static DeterministicKey generateTrezorWalletRootNode(DeterministicKey privateMasterKey) { DeterministicKey key_m_44h = HDKeyDerivation.deriveChildKey(privateMasterKey, new ChildNumber(44 | ChildNumber.HARDENED_BIT)); log.debug("key_m_44h deterministic key = " + key_m_44h); DeterministicKey key_m_44h_0h = HDKeyDerivation.deriveChildKey(key_m_44h, ChildNumber.ZERO_HARDENED); log.debug("key_m_44h_0h deterministic key = " + key_m_44h_0h); DeterministicKey key_m_44h_0h_0h = HDKeyDerivation.deriveChildKey(key_m_44h_0h, ChildNumber.ZERO_HARDENED); log.debug("key_m_44h_0h_0h = " + key_m_44h_0h_0h); return key_m_44h_0h_0h; }