All Downloads are FREE. Search and download functionalities are using the official Maven repository.

bip.com.unbound.common.crypto.BIP32 Maven / Gradle / Ivy

Go to download

This is a collection of JAVA libraries that implement Unbound cryptographic classes for JAVA provider, PKCS11 wrapper, cryptoki, and advapi

There is a newer version: 42761
Show newest version
package com.unbound.common.crypto;

import com.unbound.common.Base58;
import com.unbound.common.Converter;
import com.unbound.common.HEX;

import java.math.BigInteger;
import java.util.Arrays;

public class BIP32
{
  private final EC.Curve curve;
  private EC.Point pub = null;
  private final byte level;
  private final int childNumber;
  private byte[] parentFingerprint = new byte[4];
  private byte[] K = null;
  private byte[] C = new byte[32];

  public EC.Point getPublicKey()
  {
    if (pub==null) pub = curve.generator.mul(getPrivateKey());
    return pub;
  }
  public int getChildNumber()            { return childNumber; }
  public byte getLevel()                 { return level; }
  public byte[] getParentFingerprint()   { return parentFingerprint; }
  public byte[] getChainCode()           { return C; }
  public BigInteger getPrivateKey()
  {
    if (K==null) throw new IllegalArgumentException("Private key is absent");
    return new BigInteger(1, K);
  }

  private BIP32(EC.Curve curve, byte level, int childNumber)
  {
    this.childNumber = childNumber;
    this.level = level;
    this.curve = curve;
  }

  public static BIP32 deriveFromMaster(EC.Curve curve, byte[] seed)
  {
    String hmacSeed;
    if (curve==EC.P256) hmacSeed = "Nist256p1 seed";
    else if (curve==EC.P256k) hmacSeed = "Bitcoin seed";
    else throw new IllegalArgumentException("Curve not supported");

    BIP32 result = new BIP32(curve, (byte)0, 0);
    byte[] I = HMAC.SHA512.hmac(hmacSeed.getBytes(), seed);
    BigInteger key = Converter.binToBigNum(I, 0, 32).mod(curve.order);

    result.K = Converter.bigNumToBin(key, 32);
    result.C = Arrays.copyOfRange(I, 32, 64);

    return result;
  }

  public BIP32 derive(boolean hardened, int index)
  {
    if (index<0) throw new IllegalArgumentException("Negative index");
    BigInteger oldK = getPrivateKey();

    EC.Point point = getPublicKey();
    byte[] pointOct = point.toCompressedOct();

    byte[] I;
    byte[] indexBuf = new byte[4];
    if (hardened)
    {
      index|=0x80000000;
      Converter.setBE4(indexBuf, 0, index);
      I = new HMAC.SHA512(C).update((byte)0).update(K).update(indexBuf).end();
    }
    else
    {
      Converter.setBE4(indexBuf, 0, index);
      I = new HMAC.SHA512(C).update(pointOct).update(indexBuf).end();
    }

    BigInteger delta = Converter.binToBigNum(I,0, 32);
    BigInteger newK = oldK.add(delta).mod(curve.order);

    BIP32 derived = new BIP32(curve, (byte)(level+1), index);
    derived.K = Converter.bigNumToBin(newK, 32);
    derived.C = Arrays.copyOfRange(I, 32, 64);

    byte[] h = Ripemd160.hash(SHA256.hash(pointOct));
    derived.parentFingerprint = Arrays.copyOfRange(h, 0, 4);

    return derived;
  }

  public BIP32 derivePub(int index)
  {
    if (index<0) throw new IllegalArgumentException("Negative index");
    EC.Point point = getPublicKey();
    byte[] pointOct = point.toCompressedOct();

    byte[] I;
    byte[] indexBuf = new byte[4];
    Converter.setBE4(indexBuf, 0, index);
    I = new HMAC.SHA512(C).update(pointOct).update(indexBuf).end();

    BigInteger delta = Converter.binToBigNum(I,0, 32);

    BIP32 derived = new BIP32(curve, (byte)(level+1), index);
    derived.C = Arrays.copyOfRange(I, 32, 64);
    derived.pub = pub.add(curve.generator.mul(delta));

    byte[] h = Ripemd160.hash(SHA256.hash(pointOct));
    derived.parentFingerprint = Arrays.copyOfRange(h, 0, 4);

    return derived;
  }

  private static String encodeBase58Check(byte[] bin)
  {
    byte[] hh = SHA256.hash(SHA256.hash(bin));
    byte[] buf = new byte[bin.length+4];
    System.arraycopy(bin, 0, buf, 0, bin.length);
    System.arraycopy(hh, 0, buf, bin.length, 4);
    return Base58.encode(buf);
  }

  private String serialize(int version, byte[] buf)
  {
    byte[] out = new byte[78];
    Converter.setBE4(out, 0, version);
    out[4] = level;
    System.arraycopy(parentFingerprint, 0, out, 5, 4);
    Converter.setBE4(out, 9, childNumber);
    System.arraycopy(C, 0, out, 13, 32);
    System.arraycopy(buf, 0, out, 78-buf.length, buf.length);

    return encodeBase58Check(out);
  }

  public String serializePub()
  {
    return serializePub(true);
  }

  public String serializePub(boolean main)
  {
    EC.Point point = getPublicKey();
    byte[] pointOct = point.toCompressedOct();

    int version = main ? 0x0488B21E : 0x043587CF;
    return serialize(version, pointOct);
  }

  public String serializePrv()
  {
  return serializePrv(true);
  }

  public String serializePrv(boolean main)
  {
    int version = main ? 0x0488ADE4 : 0x04358394;
    return serialize(version, K);
  }

/*
  static class Test
  {
    public static void main(String[] args)
    {
      test_secp256k1();
      test_secp256r1();
    }

    private static void test_bip_secp256r1(String seed, String path, String fingerprint, String chainCode, String prv, String pub)
    {
      byte[] seedBin = HEX.from(seed);

      int p = 0;
      int index = 0;
      boolean hardened = false;
      BIP32 node = null;
      boolean has_node = false;

      for (int i=0; i='0' && c<='9')
        {
          has_node = false;
          hardened = false;
          index = index * 10 + c-'0';
        }
        else
        {
          assert(false);
        }
      }

      if (!has_node)
      {
        node = node.derive(hardened, index);
      }

      if (fingerprint!=null && !fingerprint.isEmpty())
      {
        byte[] f = HEX.from(fingerprint);
        assert(Arrays.equals(f,node.getParentFingerprint()));
      }

      if (chainCode!=null && !chainCode.isEmpty())
      {
        byte[] c_par = HEX.from(chainCode);
        assert(Arrays.equals(c_par,node.getChainCode()));
      }


      if (prv!=null && !prv.isEmpty())
      {
        if (prv.charAt(0)!='x')
        {
          byte[] prvBin = HEX.from(prv);
          BigInteger x = new BigInteger(1, prvBin);
          assert(x.equals(node.getPrivateKey()));
        }
        else
        {
          String s = node.serializePrv();
          assert(s.equals(prv));
        }
      }

      if (pub!=null && !pub.isEmpty())
      {
        if (pub.charAt(0)!='x')
        {
          byte[] pubBin = HEX.from(pub);
          EC.Point point = EC.Point.fromOct(EC.P256, pubBin);
          assert(point.equals(node.getPublicKey()));
        }
        else
        {
          String s = node.serializePub();
          assert(s.equals(pub));
        }
      }
    }


    private static void test_secp256r1()
    {

      //https://github.com/satoshilabs/slips/blob/master/slip-0010.md

      test_bip_secp256r1(
        "000102030405060708090a0b0c0d0e0f",
        "m",
        "00000000",
        "beeb672fe4621673f722f38529c07392fecaa61015c80c34f29ce8b41b3cb6ea",
        "612091aaa12e22dd2abef664f8a01a82cae99ad7441b7ef8110424915c268bc2",
        "0266874dc6ade47b3ecd096745ca09bcd29638dd52c2c12117b11ed3e458cfa9e8");

      test_bip_secp256r1(
        "000102030405060708090a0b0c0d0e0f",
        "m/0'",
        "be6105b5",
        "3460cea53e6a6bb5fb391eeef3237ffd8724bf0a40e94943c98b83825342ee11",
        "6939694369114c67917a182c59ddb8cafc3004e63ca5d3b84403ba8613debc0c",
        "0384610f5ecffe8fda089363a41f56a5c7ffc1d81b59a612d0d649b2d22355590c");

      test_bip_secp256r1(
        "000102030405060708090a0b0c0d0e0f",
        "m/0'/1",
        "9b02312f",
        "4187afff1aafa8445010097fb99d23aee9f599450c7bd140b6826ac22ba21d0c",
        "284e9d38d07d21e4e281b645089a94f4cf5a5a81369acf151a1c3a57f18b2129",
        "03526c63f8d0b4bbbf9c80df553fe66742df4676b241dabefdef67733e070f6844");

      test_bip_secp256r1(
        "000102030405060708090a0b0c0d0e0f",
        "m/0'/1/2'",
        "b98005c1",
        "98c7514f562e64e74170cc3cf304ee1ce54d6b6da4f880f313e8204c2a185318",
        "694596e8a54f252c960eb771a3c41e7e32496d03b954aeb90f61635b8e092aa7",
        "0359cf160040778a4b14c5f4d7b76e327ccc8c4a6086dd9451b7482b5a4972dda0");

      test_bip_secp256r1(
        "000102030405060708090a0b0c0d0e0f",
        "m/0'/1/2'/2",
        "0e9f3274",
        "ba96f776a5c3907d7fd48bde5620ee374d4acfd540378476019eab70790c63a0",
        "5996c37fd3dd2679039b23ed6f70b506c6b56b3cb5e424681fb0fa64caf82aaa",
        "029f871f4cb9e1c97f9f4de9ccd0d4a2f2a171110c61178f84430062230833ff20");

      test_bip_secp256r1(
        "000102030405060708090a0b0c0d0e0f",
        "m/0'/1/2'/2/1000000000",
        "8b2b5c4b",
        "b9b7b82d326bb9cb5b5b121066feea4eb93d5241103c9e7a18aad40f1dde8059",
        "21c4f269ef0a5fd1badf47eeacebeeaa3de22eb8e5b0adcd0f27dd99d34d0119",
        "02216cd26d31147f72427a453c443ed2cde8a1e53c9cc44e5ddf739725413fe3f4");

      test_bip_secp256r1(
        "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542",
        "m",
        "00000000",
        "96cd4465a9644e31528eda3592aa35eb39a9527769ce1855beafc1b81055e75d",
        "eaa31c2e46ca2962227cf21d73a7ef0ce8b31c756897521eb6c7b39796633357",
        "02c9e16154474b3ed5b38218bb0463e008f89ee03e62d22fdcc8014beab25b48fa");

      test_bip_secp256r1(
        "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542",
        "m/0",
        "607f628f",
        "84e9c258bb8557a40e0d041115b376dd55eda99c0042ce29e81ebe4efed9b86a",
        "d7d065f63a62624888500cdb4f88b6d59c2927fee9e6d0cdff9cad555884df6e",
        "039b6df4bece7b6c81e2adfeea4bcf5c8c8a6e40ea7ffa3cf6e8494c61a1fc82cc");

      test_bip_secp256r1(
        "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542",
        "m/0/2147483647'",
        "946d2a54",
        "f235b2bc5c04606ca9c30027a84f353acf4e4683edbd11f635d0dcc1cd106ea6",
        "96d2ec9316746a75e7793684ed01e3d51194d81a42a3276858a5b7376d4b94b9",
        "02f89c5deb1cae4fedc9905f98ae6cbf6cbab120d8cb85d5bd9a91a72f4c068c76");

      test_bip_secp256r1(
        "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542",
        "m/0/2147483647'/1",
        "218182d8",
        "7c0b833106235e452eba79d2bdd58d4086e663bc8cc55e9773d2b5eeda313f3b",
        "974f9096ea6873a915910e82b29d7c338542ccde39d2064d1cc228f371542bbc",
        "03abe0ad54c97c1d654c1852dfdc32d6d3e487e75fa16f0fd6304b9ceae4220c64");

      test_bip_secp256r1(
        "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542",
        "m/0/2147483647'/1/2147483646'",
        "931223e4",
        "5794e616eadaf33413aa309318a26ee0fd5163b70466de7a4512fd4b1a5c9e6a",
        "da29649bbfaff095cd43819eda9a7be74236539a29094cd8336b07ed8d4eff63",
        "03cb8cb067d248691808cd6b5a5a06b48e34ebac4d965cba33e6dc46fe13d9b933");

      test_bip_secp256r1(
        "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542",
        "m/0/2147483647'/1/2147483646'/2",
        "956c4629",
        "3bfb29ee8ac4484f09db09c2079b520ea5616df7820f071a20320366fbe226a7",
        "bb0a77ba01cc31d77205d51d08bd313b979a71ef4de9b062f8958297e746bd67",
        "020ee02e18967237cf62672983b253ee62fa4dd431f8243bfeccdf39dbe181387f");


      //https://github.com/backslash47/hdkey-secp256r1/blob/master/test/fixtures/hdkey.json
      test_bip_secp256r1(
        "000102030405060708090a0b0c0d0e0f",
        "m",
        "", "",
        "xprv9s21ZrQH143K3xbxu53vDH2NWbLKw5edQ3BCSX12Pknr1EA7QjAZPnd2jYvGvZ9RSwbcfeCZ5v2qZTTESRMTiAizzfQ1GUDeMWPyaXGcMfF",
        "xpub661MyMwAqRbcGSgS16avaQy74dApLYNUmG6oEuQdx6Kpt2VFxGUowawWaozRLQSe46f7nbyC5ZY8Tvvnc32WSiL3LSxFNvPgG84QVAyvBAw");

      test_bip_secp256r1(
        "000102030405060708090a0b0c0d0e0f",
        "m/0'",
        "", "",
        "xprv9vJJjmzMMcPT7vuRQ3RUihF5SFms7a4j1CPuxok5NYqMd5dWjwXnmLTh8CzdBZJwHUybU3gSkKEAm86C27yde9ziL2PmahvMQSPhWSVAyVb",
        "xpub69Hf9HXFBywkLQytW4xV5qBozHcMX2naNRKWmC9gvtNLVsxfHUr3K8nAyWB6SFgSTJXtSoNqVPBjy5qeMcEb1EZhuPwUd7Sy2tSprcR3bN5");

      test_bip_secp256r1(
        "000102030405060708090a0b0c0d0e0f",
        "m/0'/1",
        "", "",
        "xprv9wvN2XR2jhXFtoRvikiU4HhtMgFanjvmmMhRHj5KMKtHi2PN9aZPjAVWDLrjUbi5qejuMeQ3jH4ysGCVjVMMgERS3zCpv9DgbSEeHBnmR5k",
        "xpub6AuiS2wva55Z7HWPpnFURRecui65CCed8ad267UvufRGapiWh7seGxoz4e9nu9G1aBYqGsEV5RjhqLAjNWm294RZTgU8UgQ821iaPY5tazr");

      test_bip_secp256r1(
        "000102030405060708090a0b0c0d0e0f",
        "m/0'/1/2'",
        "", "",
        "xprv9z2VpTyrSEs4AL8C9v1YLnB1eH8nJZHD3Je2xDsr6ZCkKPbuuJTQHNevwSHHzswEQqojkg9RnGZPFTwUA4e9q83KCKiCu7cFr7T2gWLtdcu",
        "xpub6D1rDyWkGcRMNpCfFwYYhv7kCJyGi214QXZdkcHTetjjCBw4SqmeqAyQnj8zdxbg7xNC4JjE25XwWqxxEMKdx3vafV7J2FKJ6XEEi4hp3WE");


    }

    private static void test_secp256k1()
    {
      {
        String seed_hex = "000102030405060708090a0b0c0d0e0f";
        byte[] seed = HEX.from(seed_hex);

        BIP32 m = BIP32.deriveFromMaster(EC.P256k, seed);
        BIP32 m_0H = m.derive(true, 0);
        BIP32 m_0H_1 = m_0H.derive(false, 1);
        BIP32 m_0H_1_2H = m_0H_1.derive(true, 2);
        BIP32 m_0H_1_2H_2 = m_0H_1_2H.derive(false, 2);
        BIP32 m_0H_1_2H_2_1000000000  = m_0H_1_2H_2.derive(false, 1000000000);

        assert(m_0H_1_2H_2_1000000000.getPublicKey().equals(m_0H_1_2H_2.derivePub(1000000000).getPublicKey()));

        assert(m.serializePub().equals("xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"));
        assert(m.serializePrv().equals("xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"));

        assert(m_0H.serializePub().equals("xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw"));
        assert(m_0H.serializePrv().equals("xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7"));

        assert(m_0H_1.serializePub().equals("xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"));
        assert(m_0H_1.serializePrv().equals("xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs"));

        assert(m_0H_1_2H.serializePub().equals("xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5"));
        assert(m_0H_1_2H.serializePrv().equals("xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM"));

        assert(m_0H_1_2H_2.serializePub().equals("xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV"));
        assert(m_0H_1_2H_2.serializePrv().equals("xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334"));

        assert(m_0H_1_2H_2_1000000000.serializePub().equals("xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"));
        assert(m_0H_1_2H_2_1000000000.serializePrv().equals("xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76"));
      }

      {
        String seed_hex = "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542";
        byte[] seed = HEX.from(seed_hex);

        BIP32 m = BIP32.deriveFromMaster(EC.P256k, seed);
        BIP32 m_0 = m.derive(false, 0);
        BIP32 m_0_2147483647H = m_0.derive(true, 2147483647);
        BIP32 m_0_2147483647H_1 = m_0_2147483647H.derive(false, 1);
        BIP32 m_0_2147483647H_1_2147483646H = m_0_2147483647H_1.derive(true, 2147483646);
        BIP32 m_0_2147483647H_1_2147483646H_2 = m_0_2147483647H_1_2147483646H.derive(false, 2);

        assert(m_0_2147483647H_1_2147483646H_2.getPublicKey().equals(m_0_2147483647H_1_2147483646H.derivePub(2).getPublicKey()));

        assert(m.serializePub().equals("xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB"));
        assert(m.serializePrv().equals("xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U"));

        assert(m_0.serializePub().equals("xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"));
        assert(m_0.serializePrv().equals("xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt"));

        assert(m_0_2147483647H.serializePub().equals("xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a"));
        assert(m_0_2147483647H.serializePrv().equals("xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9"));

        assert(m_0_2147483647H_1.serializePub().equals("xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon"));
        assert(m_0_2147483647H_1.serializePrv().equals("xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef"));

        assert(m_0_2147483647H_1_2147483646H.serializePub().equals("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL"));
        assert(m_0_2147483647H_1_2147483646H.serializePrv().equals("xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc"));

        assert(m_0_2147483647H_1_2147483646H_2.serializePub().equals("xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"));
        assert(m_0_2147483647H_1_2147483646H_2.serializePrv().equals("xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j"));
      }

      {
        String seed_hex = "4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be";
        byte[] seed = HEX.from(seed_hex);

        BIP32 m = BIP32.deriveFromMaster(EC.P256k, seed);
        BIP32 m_0H = m.derive(true, 0);

        assert(m.serializePub().equals("xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13"));
        assert(m.serializePrv().equals("xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6"));

        assert(m_0H.serializePub().equals("xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y"));
        assert(m_0H.serializePrv().equals("xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L"));
      }

    }
  }*/
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy