예제 #1
0
파일: KeyPath.cs 프로젝트: xcrash/NBitcoin
		public KeyPath Derive(KeyPath derivation)
		{
			return new KeyPath(
				_Indexes
				.Concat(derivation._Indexes)
				.ToArray());
		}
예제 #2
0
        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);
        }
예제 #3
0
 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();
 }
예제 #4
0
        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);
        }
예제 #5
0
        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");
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
        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());
        }
예제 #8
0
 protected override PSBTHDKeyMatch CreateHDKeyMatch(IHDKey accountKey, KeyPath addressKeyPath, KeyValuePair <PubKey, RootedKeyPath> kv)
 {
     return(new PSBTHDKeyMatch <PSBTInput>(this, accountKey, addressKeyPath, kv));
 }
예제 #9
0
        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);
            }
        }
예제 #10
0
        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;
            }
        }
예제 #11
0
 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);
     }
 }
예제 #12
0
		public ExtKey Derive(KeyPath derivation)
		{
			ExtKey result = this;
			return derivation.Indexes.Aggregate(result, (current, index) => current.Derive(index));
		}
예제 #13
0
 public IHDScriptPubKey Derive(KeyPath keyPath)
 {
     return(new HDKeyScriptPubKey(this.hdKey.Derive(keyPath), type));
 }
예제 #14
0
 IHDKey IHDKey.Derive(KeyPath keyPath)
 {
     return(this.Derive(keyPath));
 }
예제 #15
0
        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);
            }
        }
예제 #16
0
        public ExtPubKey Derive(KeyPath derivation)
        {
            ExtPubKey result = this;

            return(derivation.Indexes.Aggregate(result, (current, index) => current.Derive(index)));
        }
예제 #17
0
        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();
        }
예제 #18
0
        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");
            }
        }