private static RawKeyBytes deriveChildKeyBytesFromPublic( DeterministicKey parent, ChildNumber childNumber) throws HDDerivationException { checkArgument(!childNumber.isHardened(), "Can't use private derivation with public keys only."); byte[] parentPublicKey = ECKey.compressPoint(parent.getPubKeyPoint()).getEncoded(); assert parentPublicKey.length == 33 : parentPublicKey.length; ByteBuffer data = ByteBuffer.allocate(37); data.put(parentPublicKey); data.putInt(childNumber.i()); byte[] i = HDUtils.hmacSha512(parent.getChainCode(), data.array()); assert i.length == 64 : i.length; byte[] il = Arrays.copyOfRange(i, 0, 32); byte[] chainCode = Arrays.copyOfRange(i, 32, 64); BigInteger ilInt = new BigInteger(1, il); assertLessThanN(ilInt, "Illegal derived key: I_L >= n"); ECPoint Ki = ECKey.CURVE.getG().multiply(ilInt).add(parent.getPubKeyPoint()); assertNonInfinity(Ki, "Illegal derived key: derived public key equals infinity."); return new RawKeyBytes(Ki.getEncoded(true), chainCode); }
private static RawKeyBytes deriveChildKeyBytesFromPrivate( DeterministicKey parent, ChildNumber childNumber) throws HDDerivationException { checkArgument(parent.hasPrivKey(), "Parent key must have private key bytes for this method."); byte[] parentPublicKey = ECKey.compressPoint(parent.getPubKeyPoint()).getEncoded(); assert parentPublicKey.length == 33 : parentPublicKey.length; ByteBuffer data = ByteBuffer.allocate(37); if (childNumber.isHardened()) { data.put(parent.getPrivKeyBytes33()); } else { data.put(parentPublicKey); } data.putInt(childNumber.i()); byte[] i = HDUtils.hmacSha512(parent.getChainCode(), data.array()); assert i.length == 64 : i.length; byte[] il = Arrays.copyOfRange(i, 0, 32); byte[] chainCode = Arrays.copyOfRange(i, 32, 64); BigInteger ilInt = new BigInteger(1, il); assertLessThanN(ilInt, "Illegal derived key: I_L >= n"); final BigInteger priv = parent.getPrivKey(); BigInteger ki = priv.add(ilInt).mod(ECKey.CURVE.getN()); assertNonZero(ki, "Illegal derived key: derived private key equals 0."); return new RawKeyBytes(ki.toByteArray(), chainCode); }