@Test public void testNHChild() throws NoSuchAlgorithmException, SignatureException, InvalidKeyException { String hxprv = "10fdbc41a4d3b8e5a0f50dd3905c1660e7476d4db3dbd9454fa4347500a633531c487e8174ffc0cfa76c3be6833111a9b8cd94446e37a76ee18bb21a7d6ea66b"; byte[] xprv = Hex.decode(hxprv); String[] hpaths = {"010400000000000000", "0100000000000000"}; byte[][] paths = new byte[][]{ Hex.decode(hpaths[0]), Hex.decode(hpaths[1]) }; byte[] res = xprv; for (int i = 0; i < hpaths.length; i++) { byte[] xpub = DeriveXpub.deriveXpub(res); res = NonHardenedChild.nhChild(paths[i], res, xpub); } }
public static byte[] nhChild(byte[] path, byte[] xprv, byte[] xpub) throws NoSuchAlgorithmException, InvalidKeyException { ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write('N'); out.write(xpub, 0, xpub.length / 2); out.write(path, 0, path.length); byte[] data = out.toByteArray(); byte[] key = new byte[xpub.length / 2]; System.arraycopy(xpub, xpub.length / 2, key, 0, xpub.length / 2); byte[] res = hmacSha512(data, key); byte[] f = new byte[res.length / 2]; System.arraycopy(res, 0, f, 0, res.length / 2); f = pruneIntermediateScalar(f); System.arraycopy(f, 0, res, 0, res.length / 2); int carry = 0; int sum = 0; for (int i = 0; i < 32; i++) { int xprvInt = xprv[i] & 0xFF; int resInt = res[i] & 0xFF; sum = xprvInt + resInt + carry; res[i] = (byte) sum; carry = sum >> 8; } if ((sum >> 8) != 0) { System.err.println("sum does not fit in 256-bit int"); } return res; }
NonHardenedChild { public static byte[] nhChild(byte[] path, byte[] xprv, byte[] xpub) throws NoSuchAlgorithmException, InvalidKeyException { ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write('N'); out.write(xpub, 0, xpub.length / 2); out.write(path, 0, path.length); byte[] data = out.toByteArray(); byte[] key = new byte[xpub.length / 2]; System.arraycopy(xpub, xpub.length / 2, key, 0, xpub.length / 2); byte[] res = hmacSha512(data, key); byte[] f = new byte[res.length / 2]; System.arraycopy(res, 0, f, 0, res.length / 2); f = pruneIntermediateScalar(f); System.arraycopy(f, 0, res, 0, res.length / 2); int carry = 0; int sum = 0; for (int i = 0; i < 32; i++) { int xprvInt = xprv[i] & 0xFF; int resInt = res[i] & 0xFF; sum = xprvInt + resInt + carry; res[i] = (byte) sum; carry = sum >> 8; } if ((sum >> 8) != 0) { System.err.println("sum does not fit in 256-bit int"); } return res; } }
NonHardenedChild { public static byte[] nhChild(byte[] path, byte[] xprv, byte[] xpub) throws NoSuchAlgorithmException, InvalidKeyException { ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write('N'); out.write(xpub, 0, xpub.length / 2); out.write(path, 0, path.length); byte[] data = out.toByteArray(); byte[] key = new byte[xpub.length / 2]; System.arraycopy(xpub, xpub.length / 2, key, 0, xpub.length / 2); byte[] res = hmacSha512(data, key); byte[] f = new byte[res.length / 2]; System.arraycopy(res, 0, f, 0, res.length / 2); f = pruneIntermediateScalar(f); System.arraycopy(f, 0, res, 0, res.length / 2); int carry = 0; int sum = 0; for (int i = 0; i < 32; i++) { int xprvInt = xprv[i] & 0xFF; int resInt = res[i] & 0xFF; sum = xprvInt + resInt + carry; res[i] = (byte) sum; carry = sum >> 8; } if ((sum >> 8) != 0) { System.err.println("sum does not fit in 256-bit int"); } return res; }  }
NonHardenedChild { public static byte[] nhChild(byte[] path, byte[] xprv, byte[] xpub) throws NoSuchAlgorithmException, InvalidKeyException { ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write('N'); out.write(xpub, 0, xpub.length / 2); out.write(path, 0, path.length); byte[] data = out.toByteArray(); byte[] key = new byte[xpub.length / 2]; System.arraycopy(xpub, xpub.length / 2, key, 0, xpub.length / 2); byte[] res = hmacSha512(data, key); byte[] f = new byte[res.length / 2]; System.arraycopy(res, 0, f, 0, res.length / 2); f = pruneIntermediateScalar(f); System.arraycopy(f, 0, res, 0, res.length / 2); int carry = 0; int sum = 0; for (int i = 0; i < 32; i++) { int xprvInt = xprv[i] & 0xFF; int resInt = res[i] & 0xFF; sum = xprvInt + resInt + carry; res[i] = (byte) sum; carry = sum >> 8; } if ((sum >> 8) != 0) { System.err.println("sum does not fit in 256-bit int"); } return res; }  static byte[] nhChild(byte[] path, byte[] xprv, byte[] xpub); static byte[] child(byte[] xprv, String[] hpaths); }
NonHardenedChild { public static byte[] nhChild(byte[] path, byte[] xprv, byte[] xpub) throws NoSuchAlgorithmException, InvalidKeyException { ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write('N'); out.write(xpub, 0, xpub.length / 2); out.write(path, 0, path.length); byte[] data = out.toByteArray(); byte[] key = new byte[xpub.length / 2]; System.arraycopy(xpub, xpub.length / 2, key, 0, xpub.length / 2); byte[] res = hmacSha512(data, key); byte[] f = new byte[res.length / 2]; System.arraycopy(res, 0, f, 0, res.length / 2); f = pruneIntermediateScalar(f); System.arraycopy(f, 0, res, 0, res.length / 2); int carry = 0; int sum = 0; for (int i = 0; i < 32; i++) { int xprvInt = xprv[i] & 0xFF; int resInt = res[i] & 0xFF; sum = xprvInt + resInt + carry; res[i] = (byte) sum; carry = sum >> 8; } if ((sum >> 8) != 0) { System.err.println("sum does not fit in 256-bit int"); } return res; }  static byte[] nhChild(byte[] path, byte[] xprv, byte[] xpub); static byte[] child(byte[] xprv, String[] hpaths);  }