コード例 #1
0
        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));
                }
        }
コード例 #2
0
        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);
                }
        }
コード例 #3
0
ファイル: CoinService.cs プロジェクト: georgehara/Cypher
        /// <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));
        }
コード例 #4
0
        /// <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);
        }
コード例 #5
0
ファイル: CoinService.cs プロジェクト: georgehara/Cypher
        /// <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));
        }
コード例 #6
0
        /// <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);
        }
コード例 #7
0
        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);
                    }
        }
コード例 #8
0
        /// <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);
        }
コード例 #9
0
        /// <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);
        }
コード例 #10
0
        /// <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);
        }
コード例 #11
0
        /// <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);
        }
コード例 #12
0
ファイル: CoinService.cs プロジェクト: KrakenOverlord/Cypher
        /// <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);
        }