[英]Using HSM as an external signer with NBitcoin
我已經使用 HSM 作為私鑰存儲實現了簽名交易,但是我遇到了一些錯誤!
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;
}
在檢查方法(builder.Check(tx))
我得到兩個錯誤:
我使用 PKCS11Introp.Net 並連接到 Utimaco HSM 以生成密鑰對和簽名操作:
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));
}
我怎樣才能使這項工作? 非常感謝
終於解決了,感謝 NBitcoin。 分享我的解決方案:
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()), ",");
}
簽到方法:
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);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.