Beispiel #1
0
        public PuzzleValue[] GeneratePuzzles()
        {
            AssertState(SolverClientStates.WaitingGeneratePuzzles);
            List <PuzzleSetElement> puzzles = new List <PuzzleSetElement>();

            for (int i = 0; i < Parameters.RealPuzzleCount; i++)
            {
                BlindFactor blind  = null;
                Puzzle      puzzle = new Puzzle(ServerKey, InternalState.Puzzle).Blind(ref blind);
                puzzles.Add(new RealPuzzle(puzzle, blind));
            }

            for (int i = 0; i < Parameters.FakePuzzleCount; i++)
            {
                PuzzleSolution solution = null;
                Puzzle         puzzle   = ServerKey.GeneratePuzzle(ref solution);
                puzzles.Add(new FakePuzzle(puzzle, solution));
            }

            _PuzzleElements = puzzles.ToArray();
            NBitcoin.Utils.Shuffle(_PuzzleElements, RandomUtils.GetInt32());
            InternalState.FakeIndexes = new int[Parameters.FakePuzzleCount];
            int fakeI = 0;

            for (int i = 0; i < _PuzzleElements.Length; i++)
            {
                _PuzzleElements[i].Index = i;
                if (_PuzzleElements[i] is FakePuzzle)
                {
                    InternalState.FakeIndexes[fakeI++] = i;
                }
            }
            InternalState.Status = SolverClientStates.WaitingCommitments;
            return(_PuzzleElements.Select(p => p.Puzzle.PuzzleValue).ToArray());
        }
Beispiel #2
0
        public State GetInternalState()
        {
            var state = Serializer.Clone(InternalState);

            if (_PuzzleElements != null)
            {
                var commitments = new ServerCommitment[_PuzzleElements.Length];
                var puzzles = new PuzzleValue[_PuzzleElements.Length];
                var fakeSolutions = new PuzzleSolution[Parameters.FakePuzzleCount];
                var blinds = new BlindFactor[Parameters.RealPuzzleCount];
                int fakeI = 0, realI = 0;
                for (int i = 0; i < _PuzzleElements.Length; i++)
                {
                    commitments[i] = _PuzzleElements[i].Commitment;
                    puzzles[i]     = _PuzzleElements[i].Puzzle.PuzzleValue;
                    var fake = _PuzzleElements[i] as FakePuzzle;
                    if (fake != null)
                    {
                        fakeSolutions[fakeI++] = fake.Solution;
                    }

                    var real = _PuzzleElements[i] as RealPuzzle;
                    if (real != null)
                    {
                        blinds[realI++] = real.BlindFactor;
                    }
                }
                state.FakeSolutions = fakeSolutions;
                state.BlindFactors  = blinds;
                state.Commitments   = commitments;
                state.Puzzles       = puzzles;
            }
            return(state);
        }
Beispiel #3
0
        public void BlindFactorTest()
        {
            BlindFactor data = new BlindFactor("aa00000000000000000000000000000000000000000000000000000000000001");

            Assert.Equal("aa00000000000000000000000000000000000000000000000000000000000001", data.ToHexString());
            BlindFactor data2 = new BlindFactor(data.GetBytes());

            Assert.Equal(data.ToHexString(), data2.ToHexString());
        }
        public void ReceiveUnsignedVoucher(UnsignedVoucherInformation voucher)
        {
            AssertState(TumblerClientSessionStates.WaitingVoucher);
            var puzzle = new Puzzle(Parameters.VoucherKey.PublicKey, voucher.Puzzle);

            InternalState.UnsignedVoucher = voucher;
            BlindFactor factor = null;

            InternalState.BlindedVoucher       = puzzle.Blind(ref factor).PuzzleValue;
            InternalState.BlindedVoucherFactor = factor;
            InternalState.Status = TumblerClientSessionStates.WaitingTumblerClientTransactionKey;
        }
        public void CanBlind()
        {
            RsaKey key = TestKeys.Default;

            PuzzleSolution solution = null;
            BlindFactor    blind    = null;

            Puzzle puzzle        = key.PubKey.GeneratePuzzle(ref solution);
            Puzzle blindedPuzzle = puzzle.Blind(ref blind);

            Assert.True(puzzle != blindedPuzzle);
            Assert.True(puzzle == blindedPuzzle.Unblind(blind));


            PuzzleSolution blindedSolution = blindedPuzzle.Solve(key);

            Assert.False(puzzle.Verify(blindedSolution));
            Assert.True(puzzle.Verify(blindedSolution.Unblind(key.PubKey, blind)));
        }
        public void CanSolvePuzzle()
        {
            RsaKey         key       = TestKeys.Default;
            PuzzleSolution solution  = null;
            var            puzzle    = key.PubKey.GeneratePuzzle(ref solution);
            PuzzleSolution solution2 = puzzle.Solve(key);

            Assert.True(puzzle.Verify(solution));
            Assert.True(solution == solution2);


            puzzle = key.PubKey.GeneratePuzzle(ref solution);
            BlindFactor    blind           = null;
            Puzzle         blindedPuzzle   = puzzle.Blind(ref blind);
            PuzzleSolution blindedSolution = key.SolvePuzzle(blindedPuzzle);
            var            unblinded       = blindedSolution.Unblind(key.PubKey, blind);

            Assert.True(unblinded == solution);
        }
        public PuzzleValue CheckCommitmentProof(ServerCommitmentsProof proof)
        {
            if (proof == null)
            {
                throw new ArgumentNullException(nameof(proof));
            }
            if (proof.FakeSolutions.Length != Parameters.FakeTransactionCount)
            {
                throw new ArgumentException("Expecting " + Parameters.FakeTransactionCount + " solutions");
            }
            if (proof.Quotients.Length != Parameters.RealTransactionCount - 1)
            {
                throw new ArgumentException("Expecting " + (Parameters.RealTransactionCount - 1) + " quotients");
            }
            AssertState(PromiseClientStates.WaitingCommitmentsProof);

            var fakeHashes = _Hashes.OfType <FakeHash>().ToArray();

            for (int i = 0; i < proof.FakeSolutions.Length; i++)
            {
                var fakeHash = fakeHashes[i];
                var solution = proof.FakeSolutions[i];

                if (solution._Value.CompareTo(Parameters.ServerKey._Key.Modulus) >= 0)
                {
                    throw new PuzzleException("Solution bigger than modulus");
                }

                if (!new Puzzle(Parameters.ServerKey, fakeHash.Commitment.Puzzle).Verify(solution))
                {
                    throw new PuzzleException("Invalid puzzle solution");
                }

                if (!IsValidSignature(solution, fakeHash, out ECDSASignature sig))
                {
                    throw new PuzzleException("Invalid ECDSA signature");
                }
            }


            var realHashes = _Hashes.OfType <RealHash>().ToArray();

            for (int i = 1; i < Parameters.RealTransactionCount; i++)
            {
                var q   = proof.Quotients[i - 1]._Value;
                var p1  = realHashes[i - 1].Commitment.Puzzle._Value;
                var p2  = realHashes[i].Commitment.Puzzle._Value;
                var p22 = p1.Multiply(Parameters.ServerKey.Encrypt(q)).Mod(Parameters.ServerKey._Key.Modulus);
                if (!p2.Equals(p22))
                {
                    throw new PuzzleException("Invalid quotient");
                }
            }

            _Hashes = _Hashes.OfType <RealHash>().ToArray(); // we do not need the fake one anymore
            InternalState.FakeIndexes = null;
            InternalState.Quotients   = proof.Quotients;
            var         puzzleToSolve = _Hashes.OfType <RealHash>().First().Commitment.Puzzle;
            BlindFactor blind         = null;
            var         blindedPuzzle = new Puzzle(Parameters.ServerKey, puzzleToSolve).Blind(ref blind);

            InternalState.BlindFactor = blind;
            InternalState.Status      = PromiseClientStates.Completed;
            return(blindedPuzzle.PuzzleValue);
        }
Beispiel #8
0
 public RealPuzzle(Puzzle puzzle, BlindFactor blindFactory)
 {
     Puzzle      = puzzle;
     BlindFactor = blindFactory;
 }
        public PuzzleValue[] CheckCommitmentProof(ServerCommitmentsProof proof)
        {
            // steps 8, 10, 12
            if (proof == null)
            {
                throw new ArgumentNullException(nameof(proof));
            }

            var FakeSolutionsCount = proof.FakeSolutions.Select(a => a.Length).Sum(); // sums the number of FakeSolutions.

            if (FakeSolutionsCount != Parameters.GetTotalFakeTransactionsCount())
            {
                throw new ArgumentException($"Expecting {Parameters.GetTotalFakeTransactionsCount()} solutions");
            }

            var QuotientsCount = proof.Quotients.Select(a => a.Length).Sum();                               // sums the number of Quotients.

            if (QuotientsCount != (Parameters.GetTotalRealTransactionsCount() - _Parameters.PaymentsCount)) // this is Q * (mu - 1)
            {
                throw new ArgumentException($"Expecting {(Parameters.GetTotalRealTransactionsCount() - _Parameters.PaymentsCount)} quotients");
            }

            AssertState(PromiseClientStates.WaitingCommitmentsProof);
            var previousSolutions = new byte[Parameters.FakeTransactionCountPerLevel][];

            previousSolutions = previousSolutions.Select(a => new byte[0]).ToArray(); // Initialize to empty
            for (int i = 0; i < _Hashes.Length; i++)
            {
                var fakeHashes = _Hashes[i].OfType <FakeHash>().ToArray();
                for (int j = 0; j < fakeHashes.Length; j++)
                {
                    // TODO: prove that the solutions are lined up in same order as the hashes.
                    var fakeHash = fakeHashes[j];
                    var solution = proof.FakeSolutions[i][j];

                    if (solution._Value.CompareTo(Parameters.ServerKey._Key.Modulus) >= 0)
                    {
                        throw new PuzzleException("Solution bigger than modulus");
                    }

                    if (!new Puzzle(Parameters.ServerKey, fakeHash.Commitment.Puzzle).Verify(solution))
                    {
                        throw new PuzzleException("Invalid puzzle solution");
                    }

                    previousSolutions[j] = Utils.Combine(solution.ToBytes(), previousSolutions[j]);

                    var paddedSolution = new PuzzleSolution(Utils.Combine(NBitcoin.Utils.ToBytes((uint)i, true), NBitcoin.Utils.ToBytes((uint)fakeHash.Index, true), previousSolutions[j]));
                    if (!IsValidSignature(paddedSolution, fakeHash, out ECDSASignature sig))
                    {
                        throw new PuzzleException("Invalid ECDSA signature");
                    }
                }
            }
            // Step 10
            for (int i = 0; i < _Hashes.Length; i++)
            {
                var realHashes = _Hashes[i].OfType <RealHash>().ToArray();
                for (int j = 1; j < realHashes.Length; j++)
                {
                    var q   = proof.Quotients[i][j - 1]._Value;
                    var p1  = realHashes[j - 1].Commitment.Puzzle._Value;
                    var p2  = realHashes[j].Commitment.Puzzle._Value;
                    var p22 = p1.Multiply(Parameters.ServerKey.Encrypt(q)).Mod(Parameters.ServerKey._Key.Modulus);
                    if (!p2.Equals(p22))
                    {
                        throw new PuzzleException("Invalid quotient");
                    }
                }
            }
            _Hashes = _Hashes.Select(a => a.OfType <RealHash>().ToArray()).ToArray(); // we do not need the fake one anymore
            InternalState.FakeColumns = null;
            InternalState.Quotients   = proof.Quotients;

            // Step 12
            // Maybe move this step outside such that we can blind and send puzzles one by one.
            BlindFactor[] blindFactors   = new BlindFactor[_Hashes.Length];
            PuzzleValue[] blindedPuzzles = new PuzzleValue[_Hashes.Length];

            for (int i = 0; i < _Hashes.Length; i++)
            {
                var puzzleToSolve = _Hashes[i].OfType <RealHash>().First().Commitment.Puzzle;
                blindedPuzzles[i] = new Puzzle(Parameters.ServerKey, puzzleToSolve).Blind(ref blindFactors[i]).PuzzleValue;
            }

            InternalState.BlindFactors = blindFactors;
            InternalState.Status       = PromiseClientStates.Completed;
            return(blindedPuzzles);
        }