public void Extkey_derivation() { // TODO More test vectors var s = Secp256K1.New(); var seed = HexUtil.from_hex("000102030405060708090a0b0c0d0e0f"); var extk = ExtendedKey.from_seed(s, seed); var derived = extk.Derive(s, 0); var sec = HexUtil.from_hex("d75f70beb2bd3b56f9b064087934bdedee98e4b5aae6280c58b4eff38847888f" ); var secretKey = SecretKey.From_slice(s, sec); var chaincode = HexUtil.from_hex("243cb881e1549e714db31d23af45540b13ad07941f64a786bbf3313b4de1df52"); var rootKeyId = HexUtil.from_hex("83e59c48297b78b34b73"); var identifier = HexUtil.from_hex("0185adb4d8b730099c93"); const int depth = 1; const uint nChild = 0; Assert.Equal(derived.Key.Value, secretKey.Value); Assert.Equal( derived.Identifier(s).Value, Identifier.From_bytes(identifier).Value ); Assert.Equal( derived.RootKeyId.Value, Identifier.From_bytes(rootKeyId).Value ); Assert.Equal(derived.Chaincode, chaincode); Assert.Equal(derived.Depth, depth); Assert.Equal(derived.NChild, nChild); }
public void BIP32_Test() { // Obtain a static seed. byte[] seed = "3E6888C1747ED36CA68AAE2FD8F3A46E8AD2AE9BD545FA7F5AABD00FB14198F4B13A2D07DD7C720A57EF0BDC293EE245C28D8B7CA68029F50B58F8D7DCCBA15F".HexToBytes(); // Derive an extended key from this ExtendedKey key = new ExtendedKey(seed); // Derive private key -> child private key -> child private key -> child hardened private key. var derived = key.GetChildKey(20).GetChildKey(40).GetChildKey(0x80000020); Assert.Equal("D26812D4F2E44A2E663B00314167DE30DF0DA771D45E85977C7AC2CA33291183", derived.InternalKey.ToPrivateKeyArray().ToHexString(), StringComparer.InvariantCultureIgnoreCase); // Derive private key -> public key -> child public key. var derivedPubKeyLater = derived.GetExtendedPublicKey().GetChildKey(30); Assert.Equal("0302BF19F1F90603E6DEE1630AB997B31742043CCFA7452A94BA1B686DCDE19A88", derivedPubKeyLater.InternalKey.ToPublicKeyArray(true, false).ToHexString(), StringComparer.InvariantCultureIgnoreCase); // Public keys cannot derive hardened children (private key must be known). Assert.ThrowsAny <ArgumentException>(() => { derivedPubKeyLater.GetChildKey(0x80000020); }); // Rebuild our key using a child and our get parent key function. var immediateChildKey = key.GetChildKey(20); var recreatedKey = immediateChildKey.GetParentPrivateKey(key.GetExtendedPublicKey()); // Verify our rebuilt key. Assert.Equal(key.InternalKey.ToPrivateKeyArray().ToHexString(), recreatedKey.InternalKey.ToPrivateKeyArray().ToHexString()); }
private Keychain(Secp256K1 secp, ExtendedKey extkey, Dictionary <string, SecretKey> keyOverrides, ConcurrentDictionary <string, uint> keyDerivationCache) { Secp = secp; Extkey = extkey; KeyOverrides = keyOverrides; KeyDerivationCache = keyDerivationCache; }
public Bip44AccountDerivation(MnemonicPhrase mnemonicPhrase, uint coinType, uint account = 0, uint change = 0, string password = null) { var coinTypeIndex = coinType.ToString(CultureInfo.InvariantCulture); var accountIndex = account.ToString(CultureInfo.InvariantCulture); var changeIndex = change.ToString(CultureInfo.InvariantCulture); _pathPrefix = $"m/44'/{coinTypeIndex}'/{accountIndex}'/{changeIndex}/"; _phrase = mnemonicPhrase; _extendedKey = new ExtendedKey(mnemonicPhrase.DeriveKeySeed(password)); }
public static Keychain From_seed(byte[] seed) { var secp = Secp256K1.WithCaps(ContextFlag.Commit); var extkey = ExtendedKey.from_seed(secp, seed); var keychain = new Keychain( secp, extkey, new Dictionary <string, SecretKey>(), new ConcurrentDictionary <string, uint>()) ; return(keychain); }
public byte[] GeneratePrivateKey(uint accountIndex) { // Obtain our indexed key path for this mnemonic. string indexedKeyPath = _pathPrefix + accountIndex.ToString(CultureInfo.InvariantCulture); // Obtain our indexed key ExtendedKey indexedKey = _extendedKey.GetChildKey(new KeyPath(indexedKeyPath)); // Obtain our private key byte[] privateKey = indexedKey.InternalKey.ToPrivateKeyArray(); return(privateKey); }
/// <summary> /// </summary> /// <param name="test"> /// </param> private static void RunTest(TestVector test) { var constHash = "Bitcoin seed".Select(Convert.ToByte).ToArray(); var headers = new CoinParameters { PublicKeyAddressVersion = 0, PrivateKeyVersion = 128 }; var seed = CryptoUtil.ConvertHex(test.strHexMaster); var key = ExtendedKey.Create(constHash, seed); var pubkey = key.GetPublicKey(); foreach (var derive in test.vDerive) { var skey = key.Serialize(); var spubkey = pubkey.Serialize(); Guard.Require(skey == derive.prv); Guard.Require(spubkey == derive.pub); var pkey = ExtendedKey.Parse(derive.prv); var ppubkey = ExtendedKey.Parse(derive.pub); var wif1 = pkey.GetKey(1).PrivateKey.ToWifKey(headers); var wif2 = key.GetKey(1).PrivateKey.ToWifKey(headers); Guard.Require(wif1 == wif2); var addr1 = ppubkey.GetKey(1).PublicKey.ToAddress(headers); var addr2 = pubkey.GetKey(1).ToAddress(headers); Guard.Require(addr1.ToString() == addr2.ToString()); key = key.GetChild(derive.nChild); if ((derive.nChild & 0x80000000) == 0) { var pubkeyn = pubkey.GetChild(derive.nChild); pubkey = key.GetPublicKey(); Guard.Require(pubkey.Master.ToAddress(headers).ToString() == pubkeyn.Master.ToAddress(headers).ToString()); } else { pubkey = key.GetPublicKey(); } } }
public void BIP44_Mnemonic_HDKeys_Test() { // Obtain our master key from a mnemonic. MnemonicPhrase mnemonicPhrase = new MnemonicPhrase("benefit already weapon attract visit kiss favorite blouse matter impulse noodle earth"); ExtendedKey extendedKey = new ExtendedKey(mnemonicPhrase.DeriveKeySeed()); // Define the key path string keyPath = "m/44'/60'/0'/0/account_index"; // Define our expected results. string[] expectedResultAddresses = { "0x02032d303958511779aAFEE078434b2413d24bC6", "0x768aB38a2f1a91234cee8A18714d73C665903c5a", "0x21891E5f8c42a4a3B65114De8C8D33102fbD8b8e", "0x48B187AA0D5ef22a52c2213aDb27E554d065f08C", "0x10Fdd87FCFf55653854B8eE94a70E0F365E55EC2", "0x219ef73681A4Cf864E23467c4EcBBf070215372d", "0xCE7d33a554f15B41504b17022A38cB7038b74B1f", "0x5942181baD62B159072db7538CCA4F70B5Cdb6D6", "0xa7925fAfF5402cE3f9D40CF2335B87377FaE1118", "0x63526C9C7137d83cd49DB6231c6383C99e5949e8", }; // Verify all of our addresses. for (int i = 0; i < expectedResultAddresses.Length; i++) { // Obtain our indexed key path for this mnemonic. string indexedKeyPath = keyPath.Replace("account_index", i.ToString(CultureInfo.InvariantCulture), StringComparison.InvariantCultureIgnoreCase); // Obtain our indexed key ExtendedKey indexedKey = extendedKey.GetChildKey(new KeyPath(indexedKeyPath)); // Obtain our public key hash byte[] addressBytes = indexedKey.InternalKey.GetPublicKeyHash(); addressBytes = addressBytes.Slice(addressBytes.Length - Address.SIZE); // Verify our address matches our expected result. Assert.Equal(expectedResultAddresses[i], addressBytes.ToHexString(true), StringComparer.InvariantCultureIgnoreCase); } }
public void Extkey_from_seed() { // TODO More test vectors var s = Secp256K1.New(); var seed = HexUtil.from_hex("000102030405060708090a0b0c0d0e0f"); var extk = ExtendedKey.from_seed(s, seed); var sec = HexUtil.from_hex("c3f5ae520f474b390a637de4669c84d0ed9bbc21742577fac930834d3c3083dd"); var secretKey = SecretKey.From_slice(s, sec); var chaincode = HexUtil.from_hex("e7298e68452b0c6d54837670896e1aee76b118075150d90d4ee416ece106ae72"); var identifier = HexUtil.from_hex("83e59c48297b78b34b73"); const int depth = 0; const uint nChild = 0; Assert.Equal(extk.Key.Value, secretKey.Value); Assert.Equal(extk.Identifier(s).Value, Identifier.From_bytes(identifier).Value); Assert.Equal(extk.RootKeyId.Value, Identifier.From_bytes(identifier).Value); Assert.Equal(extk.Chaincode, chaincode); Assert.Equal(extk.Depth, depth); Assert.Equal(extk.NChild, nChild); }
public void TestPathBip44() { const string ExpectedPubKey = "xpub6EncrYPyfQEpEmcMsHEnAXFQY5JkfMcyEWjExM8ppTtJ2y2TR7FfTjEVYxru1Ry9cYdsSkiPjZhv94KyJE8JT8bQuFKHpGzNV4cMscWeRLT"; const string ExpectedPrvKey = "xprvA1oGT2s5q2gX2HXtmFhmoPJfz3UGFtu7sHoe9xjDG8MKAAhJsZwQuvv1hgSHsCV1CDzL6pq9cFPoWgh7pV4TNKwdzCKBvm6MX5YqaoPZWDu"; const string Mnemonic = "thrive empower soon push mountain jeans chimney top jelly sorry beef hard napkin mule matrix today draft high vacuum exercise blind kitchen inflict abstract"; ////var key = CryptoService.CreateNew32ByteKeyPushEntropy(); ////var bip39 = new Bip39(Convert.FromBase64String(key.ConvertToString())); var bip39 = new Bip39(Mnemonic); var usersMasterSeed = bip39.SeedBytes; var prvkey = ExtendedKey.Create(ExtendedKey.Bitcoinseed, usersMasterSeed); var keyPath = ExtendedKeyPathBip44.CreateBip44(0).AddChild(0); var derrived = keyPath.Items.Aggregate(prvkey, (current, item) => current.GetChild(item)); var prv = derrived.Serialize(); var pub = derrived.GetPublicKey().Serialize(); Assert.AreEqual(ExpectedPubKey, pub); Assert.AreEqual(ExpectedPrvKey, prv); }