public KeyPath Derive(KeyPath derivation) { return new KeyPath( _Indexes .Concat(derivation._Indexes) .ToArray()); }
public Wallet(byte[] seed, string path = DEFAULT_PATH, IRandom random = null) : this(path, random) { Seed = seed.ToHex(); var keyPath = new KeyPath(GetMasterPath()); _masterKey = new ExtKey(Seed).Derive(keyPath); }
public static byte[] Serialize(KeyPath keyPath) { Guard.AssertKeyPath(keyPath); MemoryStream ms = new MemoryStream(); ms.WriteByte((byte)keyPath.Indexes.Length); for(int i = 0; i < keyPath.Indexes.Length; i++) { var bytes = ToBytes(keyPath.Indexes[i], false); ms.Write(bytes, 0, bytes.Length); } return ms.ToArray(); }
private EthECKey GetECKeyPair(string mneumonicWords, string passphrase, long addressIndex) { Mnemonic mneumonic = new Mnemonic(mneumonicWords); string seed = mneumonic.DeriveSeed(passphrase).ToHex(); ExtKey masterKey = new ExtKey(seed); NBitcoin.KeyPath keyPath = new NBitcoin.KeyPath(GetIndexPath(addressIndex)); ExtKey childkey = masterKey.Derive(keyPath); byte[] privateKeyBytes = childkey.PrivateKey.ToBytes(); EthECKey ethECKey = new EthECKey(privateKeyBytes, true); return(ethECKey); }
static void GenerateAddress(string basePath, Network net, string words, ScriptPubKeyType scriptPubKeyType) { Mnemonic restoreNnemo = new Mnemonic(words); Console.WriteLine("GenerateAddress ########################## Start"); ExtKey masterKey = restoreNnemo.DeriveExtKey(); for (int i = 0; i < 10; i++) { //NBitcoin.KeyPath keypth = new NBitcoin.KeyPath("m/44'/0'/0'/0/" + i); NBitcoin.KeyPath keypth = new NBitcoin.KeyPath(basePath + "/0/" + i); ExtKey key = masterKey.Derive(keypth); string address = key.PrivateKey.PubKey.GetAddress(scriptPubKeyType, net).ToString(); string privateKey = key.PrivateKey.GetBitcoinSecret(net).ToString(); Console.WriteLine($" publicKey {address} , privateKey {privateKey} "); } Console.WriteLine("GenerateAddress ########################## End"); }
public static void HdWallet1() { ExtKey d = new ExtKey(); string Path = "m/44'/60'/0'/0/x"; string words = ""; var mneumonic = new Mnemonic(words); var seed = mneumonic.DeriveSeed("123456@a").ToHex(); var masterKey = new ExtKey(seed); var d1 = new Account(masterKey.PrivateKey.ToBytes()).Address; for (int i = 0; i < 10; i++) { var keyPath = new NBitcoin.KeyPath(Path.Replace("x", i.ToString())); ExtKey extKey = masterKey.Derive(keyPath); byte[] privateKey = extKey.PrivateKey.ToBytes(); var account = new Account(privateKey); Console.WriteLine("Account index : " + i + " - Address : " + account.Address + " - Private key : " + account.PrivateKey); } }
public void MoreWalletTest() { Wallet wallet = new Wallet("赛 烂 肉 什 状 系 既 株 炼 硫 辞 州", "123456"); var pk = wallet.GetPrivateKey(0).ToHex(); //ef47fca84122c17bc312d44985ebf75cd09b4beb611204b43f9f448c86cdf5e3 var addrArray = wallet.GetAddresses(19); //获得20个地址,每一个都不一样,19 是下标 var masterKey = wallet.GetMasterKey().PrivateKey.ToHex(); //获得主钥 var publicKey = wallet.GetMasterKey().Neuter(); int index = 0; var keyPath = new NBitcoin.KeyPath(wallet.Path.Replace("x", index.ToString())); // masterKey.Derive(keyPath); var childKey = wallet.GetMasterKey().Derive((uint)index); var pubKey = wallet.GetMasterKey().Neuter(); ExtKey recovered = childKey.GetParentExtKey(pubKey); ExtKey recovered0 = wallet.GetPrivateExtKey(0).Derive(0); //得到序列为0的钱包私钥,计算它的子私钥 对应序列也是0 ExtPubKey recovered0PublicKey = wallet.GetPrivateExtKey(0).Neuter(); //得到序列为0的钱包私钥 的公钥 //var result = recovered.PrivateKey.ToHex(); var recovered0PrivateKey = recovered0.GetParentExtKey(recovered0PublicKey); Assert.Equal(wallet.GetPrivateExtKey(0).PrivateKey.ToHex(), recovered0PrivateKey.PrivateKey.ToHex()); }
protected override PSBTHDKeyMatch CreateHDKeyMatch(IHDKey accountKey, KeyPath addressKeyPath, KeyValuePair <PubKey, RootedKeyPath> kv) { return(new PSBTHDKeyMatch <PSBTInput>(this, accountKey, addressKeyPath, kv)); }
public TransactionSignature UntrustedHashSign(KeyPath keyPath, UserPin pin, LockTime lockTime, SigHash sigHashType) { using(Transport.Lock()) { MemoryStream data = new MemoryStream(); byte[] path = Serializer.Serialize(keyPath); BufferUtils.WriteBuffer(data, path); var pinBytes = pin == null ? new byte[0] : pin.ToBytes(); data.WriteByte((byte)pinBytes.Length); BufferUtils.WriteBuffer(data, pinBytes); BufferUtils.WriteUint32BE(data, (uint)lockTime); data.WriteByte((byte)sigHashType); byte[] response = ExchangeApdu(LedgerWalletConstants.LedgerWallet_CLA, LedgerWalletConstants.LedgerWallet_INS_HASH_SIGN, (byte)0x00, (byte)0x00, data.ToArray(), OK); response[0] = (byte)0x30; return new TransactionSignature(response); } }
public Transaction SignTransaction(KeyPath keyPath, ICoin[] signedCoins, Transaction[] parents, Transaction transaction) { using(Transport.Lock()) { var pubkey = GetWalletPubKey(keyPath).UncompressedPublicKey.Compress(); var parentsById = parents.ToDictionary(p => p.GetHash()); var coinsByPrevout = signedCoins.ToDictionary(c => c.Outpoint); List<TrustedInput> trustedInputs = new List<TrustedInput>(); foreach(var input in transaction.Inputs) { Transaction parent; parentsById.TryGetValue(input.PrevOut.Hash, out parent); if(parent == null) throw new KeyNotFoundException("Parent transaction " + input.PrevOut.Hash + " not found"); trustedInputs.Add(GetTrustedInput(parent, (int)input.PrevOut.N)); } var inputs = trustedInputs.ToArray(); transaction = transaction.Clone(); foreach(var input in transaction.Inputs) { ICoin previousCoin = null; coinsByPrevout.TryGetValue(input.PrevOut, out previousCoin); if(previousCoin != null) input.ScriptSig = previousCoin.GetScriptCode(); } bool newTransaction = true; foreach(var input in transaction.Inputs.AsIndexedInputs()) { ICoin coin = null; if(!coinsByPrevout.TryGetValue(input.PrevOut, out coin)) continue; UntrustedHashTransactionInputStart(newTransaction, input, inputs); newTransaction = false; UntrustedHashTransactionInputFinalizeFull(transaction.Outputs); var sig = UntrustedHashSign(keyPath, null, transaction.LockTime, SigHash.All); input.ScriptSig = PayToPubkeyHashTemplate.Instance.GenerateScriptSig(sig, pubkey); ScriptError error; if(!Script.VerifyScript(coin.TxOut.ScriptPubKey, transaction, (int)input.Index, Money.Zero, out error)) return null; } return transaction; } }
public GetWalletPubKeyResponse GetWalletPubKey(KeyPath keyPath) { using(Transport.Lock()) { Guard.AssertKeyPath(keyPath); byte[] bytes = Serializer.Serialize(keyPath); //bytes[0] = 10; byte[] response = ExchangeApdu(LedgerWalletConstants.LedgerWallet_CLA, LedgerWalletConstants.LedgerWallet_INS_GET_WALLET_PUBLIC_KEY, (byte)0x00, (byte)0x00, bytes, OK); return new GetWalletPubKeyResponse(response); } }
public ExtKey Derive(KeyPath derivation) { ExtKey result = this; return derivation.Indexes.Aggregate(result, (current, index) => current.Derive(index)); }
public IHDScriptPubKey Derive(KeyPath keyPath) { return(new HDKeyScriptPubKey(this.hdKey.Derive(keyPath), type)); }
IHDKey IHDKey.Derive(KeyPath keyPath) { return(this.Derive(keyPath)); }
internal PSBTOutput(BitcoinStream stream, PSBT parent, uint index, TxOut txOut) : base(parent) { if (txOut == null) { throw new ArgumentNullException(nameof(txOut)); } if (parent == null) { throw new ArgumentNullException(nameof(parent)); } TxOut = txOut; Index = index; byte[] k = new byte[0]; byte[] v = new byte[0]; try { stream.ReadWriteAsVarString(ref k); } catch (EndOfStreamException e) { throw new FormatException("Invalid PSBTOutput. Could not read key", e); } while (k.Length != 0) { try { stream.ReadWriteAsVarString(ref v); } catch (EndOfStreamException e) { throw new FormatException("Invalid PSBTOutput. Could not read value", e); } switch (k.First()) { case PSBTConstants.PSBT_OUT_REDEEMSCRIPT: if (k.Length != 1) { throw new FormatException("Invalid PSBTOutput. Contains illegal value in key for redeem script"); } if (redeem_script != null) { throw new FormatException("Invalid PSBTOutput, duplicate key for redeem_script"); } redeem_script = Script.FromBytesUnsafe(v); break; case PSBTConstants.PSBT_OUT_WITNESSSCRIPT: if (k.Length != 1) { throw new FormatException("Invalid PSBTOutput. Contains illegal value in key for witness script"); } if (witness_script != null) { throw new FormatException("Invalid PSBTOutput, duplicate key for redeem_script"); } witness_script = Script.FromBytesUnsafe(v); break; case PSBTConstants.PSBT_OUT_BIP32_DERIVATION: var pubkey2 = new PubKey(k.Skip(1).ToArray()); if (hd_keypaths.ContainsKey(pubkey2)) { throw new FormatException("Invalid PSBTOutput, duplicate key for hd_keypaths"); } KeyPath path = KeyPath.FromBytes(v.Skip(4).ToArray()); hd_keypaths.Add(pubkey2, Tuple.Create(new HDFingerprint(v.Take(4).ToArray()), path)); break; default: if (unknown.ContainsKey(k)) { throw new FormatException("Invalid PSBTInput, duplicate key for unknown value"); } unknown.Add(k, v); break; } stream.ReadWriteAsVarString(ref k); } }
public ExtPubKey Derive(KeyPath derivation) { ExtPubKey result = this; return(derivation.Indexes.Aggregate(result, (current, index) => current.Derive(index))); }
internal PSBTInput(BitcoinStream stream, PSBT parent, uint index, TxIn input) { Parent = parent; TxIn = input; Index = index; originalScriptSig = TxIn.ScriptSig ?? Script.Empty; originalWitScript = TxIn.WitScript ?? WitScript.Empty; byte[] k = new byte[0]; byte[] v = new byte[0]; try { stream.ReadWriteAsVarString(ref k); } catch (EndOfStreamException e) { throw new FormatException("Invalid PSBTInput. Failed to Parse key.", e); } while (k.Length != 0) { try { stream.ReadWriteAsVarString(ref v); } catch (EndOfStreamException e) { throw new FormatException("Invalid PSBTInput. Failed to parse key.", e); } switch (k.First()) { case PSBTConstants.PSBT_IN_NON_WITNESS_UTXO: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for NonWitnessUTXO"); } if (non_witness_utxo != null) { throw new FormatException("Invalid PSBTInput. Duplicate non_witness_utxo"); } non_witness_utxo = this.GetConsensusFactory().CreateTransaction(); non_witness_utxo.FromBytes(v); break; case PSBTConstants.PSBT_IN_WITNESS_UTXO: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for WitnessUTXO"); } if (witness_utxo != null) { throw new FormatException("Invalid PSBTInput. Duplicate witness_utxo"); } if (this.GetConsensusFactory().TryCreateNew <TxOut>(out var txout)) { witness_utxo = txout; } else { witness_utxo = new TxOut(); } witness_utxo.FromBytes(v); break; case PSBTConstants.PSBT_IN_PARTIAL_SIG: var pubkey = new PubKey(k.Skip(1).ToArray()); if (partial_sigs.ContainsKey(pubkey)) { throw new FormatException("Invalid PSBTInput. Duplicate key for partial_sigs"); } partial_sigs.Add(pubkey, new TransactionSignature(v)); break; case PSBTConstants.PSBT_IN_SIGHASH: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for SigHash type"); } if (!(sighash_type is null)) { throw new FormatException("Invalid PSBTInput. Duplicate key for sighash_type"); } if (v.Length != 4) { throw new FormatException("Invalid PSBTInput. SigHash Type is not 4 byte"); } var value = Utils.ToUInt32(v, 0, true); if (!Enum.IsDefined(typeof(SigHash), value)) { throw new FormatException($"Invalid PSBTInput Unknown SigHash Type {value}"); } sighash_type = (SigHash)value; break; case PSBTConstants.PSBT_IN_REDEEMSCRIPT: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for redeem script"); } if (redeem_script != null) { throw new FormatException("Invalid PSBTInput. Duplicate key for redeem_script"); } redeem_script = Script.FromBytesUnsafe(v); break; case PSBTConstants.PSBT_IN_WITNESSSCRIPT: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for witness script"); } if (witness_script != null) { throw new FormatException("Invalid PSBTInput. Duplicate key for redeem_script"); } witness_script = Script.FromBytesUnsafe(v); break; case PSBTConstants.PSBT_IN_BIP32_DERIVATION: var pubkey2 = new PubKey(k.Skip(1).ToArray()); if (hd_keypaths.ContainsKey(pubkey2)) { throw new FormatException("Invalid PSBTInput. Duplicate key for hd_keypaths"); } var masterFingerPrint = new HDFingerprint(v.Take(4).ToArray()); KeyPath path = KeyPath.FromBytes(v.Skip(4).ToArray()); hd_keypaths.Add(pubkey2, Tuple.Create(masterFingerPrint, path)); break; case PSBTConstants.PSBT_IN_SCRIPTSIG: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for final scriptsig"); } if (final_script_sig != null) { throw new FormatException("Invalid PSBTInput. Duplicate key for final_script_sig"); } final_script_sig = Script.FromBytesUnsafe(v); break; case PSBTConstants.PSBT_IN_SCRIPTWITNESS: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for final script witness"); } if (final_script_witness != null) { throw new FormatException("Invalid PSBTInput. Duplicate key for final_script_witness"); } final_script_witness = new WitScript(v); break; default: if (unknown.ContainsKey(k)) { throw new FormatException("Invalid PSBTInput. Duplicate key for unknown value"); } unknown.Add(k, v); break; } stream.ReadWriteAsVarString(ref k); } AssertSanity(); }
internal PSBT(BitcoinStream stream, Network network) { Network = network; Inputs = new PSBTInputList(); Outputs = new PSBTOutputList(); var magicBytes = stream.Inner.ReadBytes(PSBT_MAGIC_BYTES.Length); if (!magicBytes.SequenceEqual(PSBT_MAGIC_BYTES)) { throw new FormatException("Invalid PSBT magic bytes"); } // It will be reassigned in `ReadWriteAsVarString` so no worry to assign 0 length array here. byte[] k = new byte[0]; byte[] v = new byte[0]; var txFound = false; stream.ReadWriteAsVarString(ref k); while (k.Length != 0) { switch (k[0]) { case PSBTConstants.PSBT_GLOBAL_UNSIGNED_TX: if (k.Length != 1) { throw new FormatException("Invalid PSBT. Contains illegal value in key global tx"); } if (tx != null) { throw new FormatException("Duplicate Key, unsigned tx already provided"); } tx = stream.ConsensusFactory.CreateTransaction(); uint size = 0; stream.ReadWriteAsVarInt(ref size); var pos = stream.Counter.ReadenBytes; tx.ReadWrite(stream); if (stream.Counter.ReadenBytes - pos != size) { throw new FormatException("Malformed global tx. Unexpected size."); } if (tx.Inputs.Any(txin => txin.ScriptSig != Script.Empty || txin.WitScript != WitScript.Empty)) { throw new FormatException("Malformed global tx. It should not contain any scriptsig or witness by itself"); } txFound = true; break; case PSBTConstants.PSBT_GLOBAL_XPUB when XPubVersionBytes != null: if (k.Length != 1 + XPubVersionBytes.Length + 74) { throw new FormatException("Malformed global xpub."); } for (int ii = 0; ii < XPubVersionBytes.Length; ii++) { if (k[1 + ii] != XPubVersionBytes[ii]) { throw new FormatException("Malformed global xpub."); } } stream.ReadWriteAsVarString(ref v); KeyPath path = KeyPath.FromBytes(v.Skip(4).ToArray()); var rootedKeyPath = new RootedKeyPath(new HDFingerprint(v.Take(4).ToArray()), path); GlobalXPubs.Add(new ExtPubKey(k, 1 + XPubVersionBytes.Length, 74).GetWif(Network), rootedKeyPath); break; default: if (unknown.ContainsKey(k)) { throw new FormatException("Invalid PSBTInput, duplicate key for unknown value"); } stream.ReadWriteAsVarString(ref v); unknown.Add(k, v); break; } stream.ReadWriteAsVarString(ref k); } if (!txFound) { throw new FormatException("Invalid PSBT. No global TX"); } int i = 0; while (stream.Inner.CanRead && i < tx.Inputs.Count) { var psbtin = new PSBTInput(stream, this, (uint)i, tx.Inputs[i]); Inputs.Add(psbtin); i++; } if (i != tx.Inputs.Count) { throw new FormatException("Invalid PSBT. Number of input does not match to the global tx"); } i = 0; while (stream.Inner.CanRead && i < tx.Outputs.Count) { var psbtout = new PSBTOutput(stream, this, (uint)i, tx.Outputs[i]); Outputs.Add(psbtout); i++; } if (i != tx.Outputs.Count) { throw new FormatException("Invalid PSBT. Number of outputs does not match to the global tx"); } }