)] // testcase generated by nsec build public void ShouldDecryptSameDataInBothBuilds1(string hexKey, string hexPlainText, string nonceAndMacAndCipherText) { var hex = new NBitcoin.DataEncoders.HexEncoder(); var key = hex.DecodeData(hexKey); var plainText = hex.DecodeData(hexPlainText); var result = hex.DecodeData(nonceAndMacAndCipherText); var c = new ChaCha20Poly1305CryptoAlgorithm(); var actualPlainText = c.Decrypt(key, result); Assert.Equal(hex.EncodeData(plainText), hex.EncodeData(actualPlainText)); }
public string SignTransaction(string transactionHex, WalletUnsignedTransactionUnspent[] unspents, Keychain userKeychain) { var hexEncoder = new NBitcoin.DataEncoders.HexEncoder(); var extKey = ExtKey.Parse(userKeychain.ExtendedPrivateKey); var builder = new TransactionBuilder().ContinueToBuild(Transaction.Parse(transactionHex)); foreach (var unspent in unspents) { builder .AddCoins(new ScriptCoin(new OutPoint(uint256.Parse(unspent.TransactionHash), unspent.TransactionOutputIndex), new TxOut(unspent.Value, new Script(hexEncoder.DecodeData(unspent.Script))), new Script(hexEncoder.DecodeData(unspent.RedeemScript)))) .AddKeys(extKey.Derive(KeyPath.Parse($"{userKeychain.Path}/0/0{unspent.ChainPath}")).PrivateKey); } return(builder.BuildTransaction(true).ToHex()); }
public IActionResult CreateReviewerAddressAsync([FromBody] CreateReviewerAddressRequest request) { Guard.NotNull(request, nameof(request)); // checks the request is valid if (!this.ModelState.IsValid) { return(ModelStateErrors.BuildErrorResponse(this.ModelState)); } try { // calculate the Manager password hash byte[] binaryPassword = System.Text.Encoding.ASCII.GetBytes(request.RsaPassword); Org.BouncyCastle.Crypto.Digests.Sha512Digest sha = new Org.BouncyCastle.Crypto.Digests.Sha512Digest(); sha.BlockUpdate(binaryPassword, 0, binaryPassword.Length); byte[] shaOutput = new byte[512 / 8]; sha.DoFinal(shaOutput, 0); NBitcoin.DataEncoders.HexEncoder he = new NBitcoin.DataEncoders.HexEncoder(); string rsaPasswordHashHex = he.EncodeData(shaOutput); // create the multisig address PubKey[] groupMemberKeys = request.SignaturePubKeys.Select(pubKeyHex => new PubKey(pubKeyHex)).ToArray(); var scriptPubKey = PayToMultiSigTemplate .Instance .GenerateScriptPubKey(request.RequeiredSignatureCount, groupMemberKeys); PublicReviewerAddressModel model = new PublicReviewerAddressModel { PublicApiUrl = request.PublicApiUrl }; // check if the API is reachable and the address can be added to the watch list Uri apiRequestUri = new Uri(new Uri(model.PublicApiUrl), $"/api/WatchOnlyWallet/watch?address={scriptPubKey.Hash.GetAddress(this.network).ToString()}"); try { HttpWebRequest apiRequest = (HttpWebRequest)WebRequest.Create(apiRequestUri); ASCIIEncoding encoding = new ASCIIEncoding(); string postData = ""; byte[] data = encoding.GetBytes(postData); apiRequest.Method = "POST"; apiRequest.ContentType = "application/x-www-form-urlencoded"; apiRequest.ContentLength = data.Length; using (Stream stream = apiRequest.GetRequestStream()) { stream.Write(data, 0, data.Length); } HttpWebResponse apiResponse = (HttpWebResponse)apiRequest.GetResponse(); string responseString = new StreamReader(apiResponse.GetResponseStream()).ReadToEnd(); if (apiResponse.StatusCode != HttpStatusCode.OK) { throw new Exception($"The API request '{apiRequestUri.ToString()}' returned the status code '{apiResponse.StatusCode}'."); } } catch (Exception e) { throw new Exception($"The API request '{apiRequestUri.ToString()}' returned an error '{e.Message}'."); } // generate the RSA keypair for the address AsymmetricCipherKeyPair rsaKeyPair = GetRSAKeyPairFromSeed(request.RsaPassword + scriptPubKey.Hash.GetAddress(this.network).ToString()); RsaKeyParameters rsaPublicKey = rsaKeyPair.Public as RsaKeyParameters; RsaPublicKey pbk = new RsaPublicKey() { Exponent = rsaPublicKey.Exponent.ToByteArrayUnsigned(), Modulus = rsaPublicKey.Modulus.ToByteArrayUnsigned() }; RsaPrivateCrtKeyParameters rsaPrivateKey = rsaKeyPair.Private as RsaPrivateCrtKeyParameters; RsaPrivateKey prk = new RsaPrivateKey() { DP = rsaPrivateKey.DP.ToByteArrayUnsigned(), DQ = rsaPrivateKey.DQ.ToByteArrayUnsigned(), Exponent = rsaPrivateKey.Exponent.ToByteArrayUnsigned(), Modulus = rsaPrivateKey.Modulus.ToByteArrayUnsigned(), P = rsaPrivateKey.P.ToByteArrayUnsigned(), PublicExponent = rsaPrivateKey.PublicExponent.ToByteArrayUnsigned(), Q = rsaPrivateKey.Q.ToByteArrayUnsigned(), QInv = rsaPrivateKey.QInv.ToByteArrayUnsigned() }; // return all the information we have model = new PublicReviewerAddressModel { Network = this.network.ToString(), Address = scriptPubKey.Hash.GetAddress(this.network).ToString(), PublicName = request.PublicName, GroupName = request.GroupName, ValidFrom = request.ValidFrom.ToString("o"), ValidUntil = request.ValidUntil.ToString("o"), ScriptPubKeyHex = scriptPubKey.ToHex(), RsaPublicKeyHex = pbk.ToHex(), RsaPrivateKeyHex = prk.ToHex(), RsaPasswordHashHex = rsaPasswordHashHex, PublicApiUrl = request.PublicApiUrl }; ((WalletManager)this.walletManager).AddReviewerAddressToReviewerStore(model); return(this.Json(model)); } catch (Exception e) { this.logger.LogError("Exception occurred: {0}", e.ToString()); return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString())); } }
public void Fork_multisig_BTV() { string addr = "3CgCi4KGK4kx5dddLdQqKHN1nmACMKRrac"; string priv1 = "LnvAY6k625rPTDrB8jDajWgicFSPoBYZssxWyXucXw7HjvCS3XtA"; string priv2 = "Ln7dHCpAHCaJ4Y7DjamLH4B3MMozafH4Fa5U9xFsyHRXys1oV1UJ"; string rds = "5221023009742d61ebe747b295bab6a9268b9dcfbdfccdc0fcb747083068f4be57c6ef21039b1df4cbb3a9f77cc41f7cf807470498f5efd2b1ea46142d16b26fb5af7012e452ae"; Key a = Key.Parse(priv1); Key b = Key.Parse(priv2); Script redeemscript = PayToMultiSigTemplate .Instance .GenerateScriptPubKey(2, new[] { b.PubKey, a.PubKey }); var ad1 = a.PubKey.GetAddress(Network.Main).ToString(); var ad2 = b.PubKey.GetAddress(Network.Main).ToString(); // http://www.soroushjp.com/2014/12/20/bitcoin-multisig-the-hard-way-understanding-raw-multisignature-bitcoin-transactions/ //How many required (M of N) //OpcodeType.OP_2 var h = new NBitcoin.DataEncoders.HexEncoder(); Script redeemscript_fb = new Script(h.DecodeData(rds)); string pubAddress = redeemscript.Hash.GetAddress(Network.Main).ToString();//.GetScriptAddress(Network.Main).ToString(); Console.WriteLine("Address: " + pubAddress); Assert.AreEqual(addr, pubAddress); //Add some bitcoin to the multisig address var received = new Transaction(); received.Outputs.Add(new TxOut(Money.Coins(1.0m), redeemscript.Hash)); Coin coin = received.Outputs.AsCoins().First().ToScriptCoin(redeemscript); //Create a transaction requiring two signatories BitcoinAddress dest = new Key().PubKey.GetAddress(Network.Main); TransactionBuilder builder = new TransactionBuilder(); Transaction utx = builder .AddCoins(coin) .Send(dest, Money.Coins(0.9999m)) .SendFees(Money.Coins(0.0001m)) .SetChange(redeemscript.Hash) .BuildTransaction(sign: false); Console.WriteLine("Unsigned:"); Console.WriteLine(utx.ToHex()); Transaction sa = builder .AddCoins(coin) .AddKeys(a) .SignTransaction(utx, SigHash.ForkIdBTV, "BTV"); Console.WriteLine("sa:"); Console.WriteLine(sa.ToHex()); Transaction sb = builder .AddCoins(coin) .AddKeys(b) .SignTransaction(sa, SigHash.ForkIdBTV, "BTV"); Console.WriteLine("sb:"); Console.WriteLine(sb.ToHex()); Transaction stx = //sb; builder .AddCoins(coin) .AddKeys(a) .AddKeys(b) .SignTransaction(utx, SigHash.ForkIdBTV, "BTV"); // builder // .AddCoins(coin) // .CombineSignatures("BTV", sa, sb); Console.WriteLine("stx:"); Console.WriteLine(stx.ToHex()); var res = builder.Verify(stx, "BTV"); Assert.IsTrue(res); }
public async Task <WalletUnsignedTransaction> CreateTransactionAsync(Dictionary <string, long> recepients, long?fee = null, long?feeRate = null, int feeTxConfirmTarget = 2, int minConfirms = 1, bool enforceMinConfirmsForChange = true, long minUnspentSize = 5460, bool?instant = null, CancellationToken cancellationToken = default(CancellationToken)) { var hexEncoder = new NBitcoin.DataEncoders.HexEncoder(); var builder = new TransactionBuilder(); builder.DustPrevention = true; var totalValue = recepients.Values.Sum(); var unspents = await GetUnspentListAsync(instant, totalValue, null, null, minUnspentSize, cancellationToken); var changeAddress = await CreateAddressAsync(1, cancellationToken); builder.SetChange(_client.Network.CreateBitcoinAddress(changeAddress.Address)); foreach (var unspent in unspents.Unspents) { builder.AddCoins(new ScriptCoin(new OutPoint(uint256.Parse(unspent.TransactionHash), unspent.TransactionOutputIndex), new TxOut(unspent.Value, new Script(hexEncoder.DecodeData(unspent.Script))), new Script(hexEncoder.DecodeData(unspent.RedeemScript)))); } foreach (var recipient in recepients) { builder.Send(_client.Network.CreateBitcoinAddress(recipient.Key), recipient.Value); } var billingFee = await GetBillingFeeAsync(totalValue, instant ?? false, cancellationToken); if (billingFee > 0) { var billingAddress = await _client.Billing.GetAddressAsync(cancellationToken); billingFee = (long)Math.Min(billingFee, totalValue * 0.002); builder.Send(_client.Network.CreateBitcoinAddress(billingAddress), billingFee); } long finnalFee = 0; if (fee.HasValue) { builder.SendFees(fee.Value); finnalFee = fee.Value; } else if (feeRate.HasValue) { var estimatedFeeRate = new FeeRate(feeRate.Value); builder.SendEstimatedFees(estimatedFeeRate); finnalFee = builder.EstimateFees(estimatedFeeRate).Satoshi; } else { var estimateFee = await _client.Transactions.EstimateFeesAsync(feeTxConfirmTarget, cancellationToken); var estimatedFeeRate = new FeeRate(estimateFee.FeePerKb); builder.SendEstimatedFees(estimatedFeeRate); finnalFee = builder.EstimateFees(estimatedFeeRate).Satoshi; } var transactionHex = builder.BuildTransaction(false).ToHex(); return(new WalletUnsignedTransaction { WalletId = _id, TransactionHex = transactionHex, Fee = finnalFee, ChangeAddress = new WalletUnsignedTransactionAddress { Address = changeAddress.Address, Path = changeAddress.Path }, WalletKeychains = (await GetAsync()).Keychains.Keychains.Select(k => new WalletUnsignedTransactionKeychain { ExtendedPublicKey = k.ExtendedPublicKey, Path = k.Path }).ToArray(), Unspents = unspents.Unspents.Select(u => new WalletUnsignedTransactionUnspent { RedeemScript = u.RedeemScript, Script = u.Script, ChainPath = u.ChainPath, TransactionHash = u.TransactionHash, TransactionOutputIndex = u.TransactionOutputIndex, Value = u.Value }).ToArray() }); }