public void Commit_Sum() { using (var secp256k1 = new Secp256k1()) using (var pedersen = new Pedersen()) { string ToHex(byte[] data) { return(BitConverter.ToString(data).Replace("-", string.Empty)); } var blindA = secp256k1.CreatePrivateKey(); var blindB = secp256k1.CreatePrivateKey(); var commitA = pedersen.Commit(3, blindA); var commitB = pedersen.Commit(2, blindB); var blindC = pedersen.BlindSum(new List <byte[]> { blindA, blindB }, new List <byte[]> { }); var commitC = pedersen.Commit(3 + 2, blindC); var commitD = pedersen.CommitSum(new List <byte[]> { commitA, commitB }, new List <byte[]> { }); Assert.Equal(ToHex(commitC), ToHex(commitD)); var blindE = pedersen.BlindSum(new List <byte[]> { blindA }, new List <byte[]> { blindB }); var commitE = pedersen.Commit(3 - 2, blindE); var commitF = pedersen.CommitSum(new List <byte[]> { commitA }, new List <byte[]> { commitB }); Assert.Equal(ToHex(commitE), ToHex(commitF)); } }
static void TestToPublicKey() { using (var secp256k1 = new Secp256k1()) using (var pedersen = new Pedersen()) { var blinding = secp256k1.CreatePrivateKey(); var commitPos = pedersen.Commit(0, blinding); var commitNeg = pedersen.Commit(0, blinding); var blindSum = pedersen.BlindSum(new List <byte[]> { blinding, blinding }, new List <byte[]> { }); var commitSum = pedersen.CommitSum(new List <byte[]> { commitPos }, new List <byte[]> { commitNeg }); var msg = "Message for signing"; var msgBytes = Encoding.UTF8.GetBytes(msg); var msgHash = System.Security.Cryptography.SHA256.Create().ComputeHash(msgBytes); var sig = secp256k1.Sign(msgHash, blinding); var pubKey = pedersen.ToPublicKey(commitSum); var verified1 = secp256k1.Verify(sig, msgHash, pubKey); var pub = secp256k1.CreatePublicKey(blinding); } }
/// <summary> /// Builds the receiver. /// </summary> /// <returns>The receiver.</returns> public TaskResult <bool> Receiver(SecureString secret, ulong input, out CoinDto coin, out byte[] blind, out byte[] salt) { using (var pedersen = new Pedersen()) { salt = Cryptography.RandomBytes(16); coin = MakeSingleCoin(secret, salt.ToHex().ToSecureString(), NewStamp(), -1); blind = DeriveKey(input, coin.Stamp, coin.Version, secret, salt.ToHex().ToSecureString()); try { var blindSum = pedersen.BlindSum(new List <byte[]> { blind }, new List <byte[]> { }); var commitPos = pedersen.Commit(input, blind); var commitSum = pedersen.CommitSum(new List <byte[]> { commitPos }, new List <byte[]> { }); AttachEnvelope(blindSum, commitSum, input, secret, salt.ToHex().ToSecureString(), ref coin); } catch (Exception ex) { logger.LogError($"Message: {ex.Message}\n Stack: {ex.StackTrace}"); return(TaskResult <bool> .CreateFailure(ex)); } } return(TaskResult <bool> .CreateSuccess(true)); }
/// <summary> /// /// </summary> /// <param name="coinbase"></param> /// <param name="solution"></param> /// <param name="runningDistribution"></param> /// <returns></returns> public VerifyResult VerifyCoinbaseTransaction(Vout coinbase, ulong solution, decimal runningDistribution) { Guard.Argument(coinbase, nameof(coinbase)).NotNull(); Guard.Argument(solution, nameof(solution)).NotZero().NotNegative(); Guard.Argument(runningDistribution, nameof(runningDistribution)).NotZero().NotNegative(); if (coinbase.Validate().Any()) { return(VerifyResult.UnableToVerify); } if (coinbase.T != CoinType.Coinbase) { return(VerifyResult.UnableToVerify); } var verifyNetworkShare = VerifyNetworkShare(solution, coinbase.A.DivWithNanoTan(), runningDistribution); if (verifyNetworkShare == VerifyResult.UnableToVerify) { return(verifyNetworkShare); } using var pedersen = new Pedersen(); var commitSum = pedersen.CommitSum(new List <byte[]> { coinbase.C }, new List <byte[]> { coinbase.C }); return(commitSum == null ? VerifyResult.Succeed : VerifyResult.UnableToVerify); }
/// <summary> /// Builds the sender. /// </summary> /// <returns>The sender.</returns> public async Task <TaskResult <CoinDto> > Sender(Session session, PurchaseDto purchase) { CoinDto coin = null; using (var pedersen = new Pedersen()) { try { //TODO: Refactor signature to handle lambda expressions.. var txnsAll = await unitOfWork.GetTransactionRepository().All(session); if (txnsAll.Result?.Any() != true) { throw new Exception("No transactions found!"); } var txns = txnsAll.Result.Where(tx => purchase.Chain.Any(id => id == Guid.Parse(tx.TransactionId))); var received = txns.FirstOrDefault(tx => tx.TransactionType == TransactionType.Receive); coin = MakeSingleCoin(session.MasterKey, received.Salt.ToSecureString(), purchase.Stamp, purchase.Version); var blindNeg = DeriveKey(purchase.Input, received.Stamp, coin.Version, session.MasterKey, received.Salt.ToSecureString()); var commitNeg = pedersen.Commit(purchase.Input, blindNeg); var commitNegs = txns.Where(tx => tx.TransactionType == TransactionType.Send) .Select(c => pedersen.Commit(c.Amount, DeriveKey(c.Amount, c.Stamp, c.Version, session.MasterKey, received.Salt.ToSecureString()))).ToList(); commitNegs.Add(commitNeg); var blindNegSums = txns.Where(tx => tx.TransactionType == TransactionType.Send) .Select(c => DeriveKey(c.Amount, c.Stamp, c.Version, session.MasterKey, received.Salt.ToSecureString())).ToList(); blindNegSums.Add(blindNeg); var blindSum = pedersen.BlindSum(new List <byte[]> { received.Blind.FromHex() }, blindNegSums); var commitSum = pedersen.CommitSum(new List <byte[]> { received.Commitment.FromHex() }, commitNegs); AttachEnvelope(blindSum, commitSum, purchase.Output, session.MasterKey, received.Salt.ToSecureString(), ref coin); } catch (Exception ex) { logger.LogError($"Message: {ex.Message}\n Stack: {ex.StackTrace}"); return(TaskResult <CoinDto> .CreateFailure(ex)); } } return(TaskResult <CoinDto> .CreateSuccess(coin)); }
/// <summary> /// Builds the sender. /// </summary> /// <returns>The sender.</returns> public CoinService BuildSender(SecureString secret) { using (var secp256k1 = new Secp256k1()) using (var pedersen = new Pedersen()) using (var rangeProof = new RangeProof()) { Stamp(TransactionCoin().Stamp); Version(TransactionCoin().Version); MakeSingleCoin(secret); try { var received = TransactionCoin().Chain.FirstOrDefault(tx => tx.TransactionType == TransactionType.Receive); var blindNeg = DeriveKey(TransactionCoin().Input, received.Stamp, Coin().Version, secret); var commitNeg = pedersen.Commit(TransactionCoin().Input, blindNeg); var commitNegs = TransactionCoin().Chain .Where(tx => tx.TransactionType == TransactionType.Send) .Select(c => pedersen.Commit(c.Amount, DeriveKey(c.Amount, c.Stamp, c.Version, secret))).ToList(); commitNegs.Add(commitNeg); var blindNegSums = TransactionCoin().Chain .Where(tx => tx.TransactionType == TransactionType.Send) .Select(c => DeriveKey(c.Amount, c.Stamp, c.Version, secret)).ToList(); blindNegSums.Add(blindNeg); var blindSum = pedersen.BlindSum(new List <byte[]> { received.Blind.FromHex() }, blindNegSums); var commitSum = pedersen.CommitSum(new List <byte[]> { received.Commitment.FromHex() }, commitNegs); AttachEnvelope(secp256k1, pedersen, rangeProof, blindSum, commitSum, TransactionCoin().Output, secret); } catch (Exception ex) { logger.LogError($"Message: {ex.Message}\n Stack: {ex.StackTrace}"); throw ex; } } return(this); }
static void TestRangeProofOnBlock() { using (var secp256k1 = new Secp256k1()) using (var pedersen = new Pedersen()) using (var rangeProof = new RangeProof()) { var blinding = secp256k1.CreatePrivateKey(); ulong posValue = NaT(3434545); ulong negValue = NaT(1.123456789123456789); var diff = posValue - negValue; var blindPos = pedersen.BlindSwitch(posValue, blinding); var blindNeg = pedersen.BlindSwitch(negValue, blinding); var blindSum = pedersen.BlindSum(new List <byte[]> { blindPos }, new List <byte[]> { blindNeg }); var commitPos = pedersen.Commit(posValue, blindPos); var commitNeg = pedersen.Commit(negValue, blindNeg); var commitSum = pedersen.CommitSum(new List <byte[]> { commitPos }, new List <byte[]> { commitNeg }); var isVerified = pedersen.VerifyCommitSum(new List <byte[]> { commitPos }, new List <byte[]> { commitNeg, commitSum }); var commitChange = pedersen.Commit(diff, blinding); var msg = "Message for signing"; var msgBytes = Encoding.UTF8.GetBytes(msg); var msgHash = System.Security.Cryptography.SHA256.Create().ComputeHash(msgBytes); var proofStruct = rangeProof.Proof(0, diff, blindSum, commitSum, msgHash); var verified = rangeProof.Verify(commitSum, proofStruct); } }
/// <summary> /// Builds the receiver. /// </summary> /// <returns>The receiver.</returns> public CoinService BuildReceiver(SecureString secret) { using (var secp256k1 = new Secp256k1()) using (var pedersen = new Pedersen()) using (var rangeProof = new RangeProof()) { Stamp(NewStamp()); Version(-1); MakeSingleCoin(secret); var blind = DeriveKey(TransactionCoin().Input, Stamp(), Coin().Version, secret); byte[] blindSum = new byte[32]; try { blindSum = pedersen.BlindSum(new List <byte[]> { blind }, new List <byte[]> { }); var commitPos = pedersen.Commit(TransactionCoin().Input, blind); var commitSum = pedersen.CommitSum(new List <byte[]> { commitPos }, new List <byte[]> { }); AttachEnvelope(secp256k1, pedersen, rangeProof, blindSum, commitSum, TransactionCoin().Input, secret); transactionCoin.Blind = blindSum.ToHex(); } catch (Exception ex) { logger.LogError($"Message: {ex.Message}\n Stack: {ex.StackTrace}"); throw ex; } } return(this); }
/// <summary> /// </summary> /// <param name="transaction"></param> /// <returns></returns> public VerifyResult VerifyCommitSum(Transaction transaction) { Guard.Argument(transaction, nameof(transaction)).NotNull(); try { if (transaction.Validate().Any()) { return(VerifyResult.UnableToVerify); } using var pedersen = new Pedersen(); for (var i = 0; i < transaction.Vout.Length / 3; i++) { var fee = transaction.Vout[i].C; var payment = transaction.Vout[i + 1].C; var change = transaction.Vout[i + 2].C; var commitSumBalance = pedersen.CommitSum(new List <byte[]> { fee, payment, change }, new List <byte[]>()); if (!pedersen.VerifyCommitSum(new List <byte[]> { commitSumBalance }, new List <byte[]> { fee, payment, change })) { return(VerifyResult.UnableToVerify); } } } catch (Exception ex) { _logger.Here().Error(ex, "Unable to verify the committed sum"); return(VerifyResult.UnableToVerify); } return(VerifyResult.Succeed); }
/// <summary> /// </summary> /// <param name="transaction"></param> /// <returns></returns> public VerifyResult VerifyTransactionFee(Transaction transaction) { Guard.Argument(transaction, nameof(transaction)).NotNull(); var output = transaction.Vout.First(); if (output.T != CoinType.Fee) { return(VerifyResult.UnableToVerify); } var feeRate = Fee(FeeNByte); if (output.A != feeRate) { return(VerifyResult.UnableToVerify); } using var pedersen = new Pedersen(); var commitSum = pedersen.CommitSum(new List <byte[]> { output.C }, new List <byte[]> { output.C }); return(commitSum == null ? VerifyResult.Succeed : VerifyResult.UnableToVerify); }
/// <summary> /// Builds the coin. /// </summary> /// <returns>The coin.</returns> /// <param name="blindSum">Blind sum.</param> /// <param name="commitPos">Commit position.</param> /// <param name="commitNeg">Commit neg.</param> private CoinDto BuildCoin(byte[] blindSum, byte[] commitPos, byte[] commitNeg, bool isReceiver = false) { Guard.Argument(blindSum, nameof(blindSum)).NotNull().MaxCount(32); Guard.Argument(commitPos, nameof(commitPos)).NotNull().MaxCount(33); Guard.Argument(commitNeg, nameof(commitNeg)).NotNull().MaxCount(33); CoinDto coin = null; bool isVerified; using (var secp256k1 = new Secp256k1()) using (var pedersen = new Pedersen()) using (var rangeProof = new RangeProof()) { try { var commitSum = pedersen.CommitSum(new List <byte[]> { commitPos }, new List <byte[]> { commitNeg }); var naTInput = NaT(Input()); var naTOutput = NaT(Output()); var naTChange = naTInput - naTOutput; isVerified = isReceiver ? pedersen.VerifyCommitSum(new List <byte[]> { commitPos, commitNeg }, new List <byte[]> { Commit(naTOutput, blindSum) }) : pedersen.VerifyCommitSum(new List <byte[]> { commitPos }, new List <byte[]> { commitNeg, commitSum }); if (!isVerified) { throw new ArgumentOutOfRangeException(nameof(isVerified), "Verify commit sum failed."); } var(k1, k2) = Split(blindSum, isReceiver); coin = MakeSingleCoin(); coin.Envelope.Commitment = isReceiver ? Commit(naTOutput, blindSum).ToHex() : commitSum.ToHex(); coin.Envelope.Proof = k2.ToHex(); coin.Envelope.PublicKey = pedersen.ToPublicKey(Commit(0, k1)).ToHex(); coin.Envelope.Signature = secp256k1.Sign(Hash(coin), k1).ToHex(); coin.Hash = Hash(coin).ToHex(); proofStruct = isReceiver ? rangeProof.Proof(0, naTOutput, blindSum, coin.Envelope.Commitment.FromHex(), coin.Hash.FromHex()) : rangeProof.Proof(0, naTChange, blindSum, coin.Envelope.Commitment.FromHex(), coin.Hash.FromHex()); isVerified = rangeProof.Verify(coin.Envelope.Commitment.FromHex(), proofStruct); if (!isVerified) { throw new ArgumentOutOfRangeException(nameof(isVerified), "Range proof failed."); } } catch (Exception ex) { logger.LogError($"Message: {ex.Message}\n Stack: {ex.StackTrace}"); } } return(coin); }
/// <summary> /// Builds the coin. /// </summary> /// <returns>The coin.</returns> /// <param name="blindSum">Blind sum.</param> /// <param name="commitPos">Commit position.</param> /// <param name="commitNeg">Commit neg.</param> private CoinDto BuildCoin(byte[] blindSum, byte[] commitPos, byte[] commitNeg, bool receiver = false) { if (blindSum == null) { throw new ArgumentNullException(nameof(blindSum)); } if (blindSum.Length > 32) { throw new IndexOutOfRangeException(nameof(blindSum)); } if (commitPos == null) { throw new ArgumentNullException(nameof(commitPos)); } if (commitPos.Length > 33) { throw new IndexOutOfRangeException(nameof(commitPos)); } if (commitNeg == null) { throw new ArgumentNullException(nameof(commitNeg)); } if (commitNeg.Length > 33) { throw new IndexOutOfRangeException(nameof(commitNeg)); } CoinDto coin; bool isVerified; using (var secp256k1 = new Secp256k1()) using (var pedersen = new Pedersen()) { var commitSum = pedersen.CommitSum(new List <byte[]> { commitPos }, new List <byte[]> { commitNeg }); isVerified = receiver ? pedersen.VerifyCommitSum(new List <byte[]> { commitPos, commitNeg }, new List <byte[]> { Commit((ulong)Output(), blindSum) }) : pedersen.VerifyCommitSum(new List <byte[]> { commitPos }, new List <byte[]> { commitNeg, commitSum }); if (!isVerified) { throw new Exception(nameof(isVerified)); } var(k1, k2) = Split(blindSum); coin = MakeSingleCoin(); coin.Envelope.Commitment = commitSum.ToHex(); coin.Envelope.Proof = k2.ToHex(); coin.Envelope.PublicKey = pedersen.ToPublicKey(Commit(0, k1)).ToHex(); coin.Envelope.Signature = secp256k1.Sign(Hash(coin), k1).ToHex(); coin.Hash = Hash(coin).ToHex(); } return(coin); }