首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用NBitcoin作为外部签名器

用NBitcoin作为外部签名器
EN

Stack Overflow用户
提问于 2022-08-11 06:17:07
回答 1查看 63关注 0票数 -1

我已经实现了使用HSM作为私钥存储的签名事务,但是我遇到了一些错误!

代码语言:javascript
复制
        var network = Network.TestNet;

        var destination = BitcoinAddress.Create(receiverAddress, network);
        var sender = BitcoinAddress.Create(senderAddress, network);

        var unspentCoins = (await GetUnSpentCoins(senderAddress, network));
        var builder = network.CreateTransactionBuilder();
        var tx = builder
            .AddCoins(unspentCoins)
            .Send(destination, Money.Coins(0.00001M))
            .SubtractFees()
            .SendEstimatedFees(new FeeRate(1m))
            .SetChange(sender.ScriptPubKey)
            .BuildTransaction(false);

        var wallet = HSMWallet.Load(walletName);
        var signedTx = wallet.SignTransaction(tx.ToHex());

        var pubKey = new NBitcoin.PubKey(wallet.PubKey.RawPubKey);
        var signature = new TransactionSignature(Encoders.Hex.DecodeData(signedTx));
        builder
            .AddKnownSignature(pubKey, signature, unspentCoins[0].Outpoint)
            .SetSigningOptions(SigHash.All);

        builder.SignTransactionInPlace(tx);

        var error = builder.Check(tx);

        var verify = builder.Verify(tx);
        if (verify)
        {
            var result = await BroadcastTransaction(tx.ToHex(), Settings.BlockcypherToken, network);
            return result;

        }

在check方法(builder.Check(tx))中,我得到了两个错误:

输入0 (SigHashType)}

  • {Fee上的
  1. {脚本错误太低,实际为0.00000226,策略最小为0.00000258}

我使用PKCS11Introp.Net并连接到Utimaco HSM来生成密钥对和签名操作:

代码语言:javascript
复制
public string SignTransaction(string hex)

    {
        var mechanism = Session.Factories.MechanismFactory.Create(CKM.CKM_ECDSA);

        var dataHash = Digest(Digest(Convert.FromHexString(hex), CKM.CKM_SHA256), CKM.CKM_SHA256);

        var signature = Session.Sign(mechanism, PrivateKeyHandle, dataHash);

        Session.Verify(mechanism, PublicKeyHandle, dataHash, signature, out bool isValid);

        if (isValid == false)
            throw new Exception("error in signing transaction!");

        return ConvertUtils.BytesToHexString(ConstructEcdsaSigValue(signature));

    }

我怎么才能把这事做好?非常感谢

EN

回答 1

Stack Overflow用户

发布于 2022-08-14 07:22:06

多亏了NBitcoin,它终于解决了。分享我的解决方案:

代码语言:javascript
复制
public async Task<string> MakePayment(string walletName, string receiverAddress, decimal amount)
        {
            var network = Settings.Network == BitcoinNetwork.TestNet ? Network.TestNet : Network.Main;
            var hsmWallet = HSMWallet.Load(walletName, Session);
            var pubKey = new NBitcoin.PubKey(hsmWallet.PubKey.RawPubKey);

            var destination = BitcoinAddress.Create(receiverAddress, network);
            var sender = pubKey.GetAddress(ScriptPubKeyType.Legacy, network).ToString();

            var unspentCoins = GetUnSpentCoins(sender, network) ?? throw new Exception("no more mony to spend!");

            var builder = network.CreateTransactionBuilder();
            var unsignedTx = builder
                .AddCoins(unspentCoins)
                .Send(destination.ScriptPubKey, Money.Coins(amount))
                .SendEstimatedFees(new FeeRate(2m))
                .SetChange(pubKey)
                .BuildTransaction(sign: false);

            var rebuild = network.CreateTransactionBuilder();
            rebuild.AddCoins(unspentCoins);

            foreach (var coin in unspentCoins)
            {
                var indexedIn = unsignedTx.Inputs.FindIndexedInput(coin.Outpoint);
                if (indexedIn == null) continue;
                var signHash = indexedIn.GetSignatureHash(coin, SigHash.All);
                var sign = hsmWallet.SignTransaction(signHash.ToBytes());

                var signature = new TransactionSignature(sign, SigHash.All).MakeCanonical();

                rebuild.AddKnownSignature(pubKey, signature, coin.Outpoint);
            }

            var signedTx = rebuild.SignTransaction(unsignedTx);

            var error = rebuild.Check(signedTx);

            var verify = rebuild.Verify(signedTx);
            if (verify)
            {
                var result = await BroadcastTransaction(signedTx.ToHex(), Settings.BlockcypherToken, network);
                return signedTx.GetHash().ToString();

            }

            return string.Concat(error.Select(e => e.ToString()), ",");
        }

符号法:

代码语言:javascript
复制
public byte[] SignTransaction(byte[] signHash)
        {
            var mechanism = Session.Factories.MechanismFactory.Create(CKM.CKM_ECDSA);

            var signature = Session.Sign(mechanism, PrivateKeyHandle, signHash);

            Session.Verify(mechanism, PublicKeyHandle, signHash, signature, out bool isValid);

            if (isValid == false)
                throw new Exception("error in signing transaction!");

            return ConstructEcdsaSigValue(signature);

        }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73316066

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档