Пример #1
0
        public ServerCommitment[][] SignHashes(SignaturesRequest sigRequest)
        {
            // Almost done, just need to confirm a typo and a function.
            // Step 5

            if (sigRequest == null)
            {
                throw new ArgumentNullException(nameof(sigRequest));
            }

            var hashesCount = sigRequest.Hashes.Select(a => a.Length).Sum();

            if (hashesCount != Parameters.GetTotalTransactionsCount())
            {
                throw new ArgumentException($"Incorrect number of hashes, expected {Parameters.GetTotalTransactionsCount()}");
            }

            AssertState(PromiseServerStates.WaitingHashes);
            // 2D array of pairs of puzzles and promises (z_i, c_i).
            var promises = new ServerCommitment[Parameters.PaymentsCount][];
            // 2D array of encrypted signatures with their solutions.
            var encryptedSignatures = new EncryptedSignature[Parameters.PaymentsCount][];
            // 1-D array is used to store the epsilons for each column to be used when Hashing.
            var previousSolutions = new byte[Parameters.GetTotalTransactionsCountPerLevel()][];

            previousSolutions = previousSolutions.Select(a => new byte[0]).ToArray(); // Initialize to empty array of bytes
            for (int i = 0; i < Parameters.PaymentsCount; i++)
            {
                promises[i]            = new ServerCommitment[sigRequest.Hashes[i].Length]; // Initialization
                encryptedSignatures[i] = new EncryptedSignature[promises[i].Length];        // Initialization
                for (int j = 0; j < promises[i].Length; j++)
                {
                    var hash = sigRequest.Hashes[i][j];
                    // Sign the hash value
                    var ecdsa = InternalState.EscrowKey.Sign(hash);
                    // Convert Signature to Bytes.
                    var ecdsaDER = ecdsa.ToDER();
                    // This can be replaced by "Utils.GenerateEncryptableInteger(Key)" if padding when XORing is not important.
                    var key = (new XORKey(Parameters.ServerKey)).ToBytes(); // This just generates a random epsilon.
                    // Append the new epsilon to the list of epsilons we have for that column to create "epsilon_{i-1,j}|| . . . , epsilon_{0,j}".
                    previousSolutions[j] = Utils.Combine(key, previousSolutions[j]);
                    // Create the padded solution with the following format "i||j||epsilon_{i,j}||epsilon_{i-1,j}|| . . . , epsilon_{0,j}"
                    var paddedSolutions = new PuzzleSolution(Utils.Combine(NBitcoin.Utils.ToBytes((uint)i, true), NBitcoin.Utils.ToBytes((uint)j, true), previousSolutions[j]));
                    // Hash and XOR the padded solution with the signature we have.
                    var            promise  = XORKey.XOR(paddedSolutions._Value.ToByteArrayUnsigned(), ecdsaDER); // This function needs to be approved "XOR".
                    PuzzleSolution solution = new PuzzleSolution(key);                                            // Epsilon
                    // Encrypt the epsilon value using RSA
                    var puzzle = Parameters.ServerKey.GeneratePuzzle(ref solution);
                    promises[i][j]            = new ServerCommitment(puzzle.PuzzleValue, promise);
                    encryptedSignatures[i][j] = new EncryptedSignature(ecdsa, hash, solution);
                }
            }

            InternalState.Status = PromiseServerStates.WaitingRevelation;
            InternalState.EncryptedSignatures = encryptedSignatures;
            InternalState.FakeIndexesHash     = sigRequest.FakeIndexesHash;
            return(promises);
        }
Пример #2
0
        public State GetInternalState()
        {
            State state = Serializer.Clone(InternalState);

            state.Salts         = null;
            state.FeeVariations = null;
            state.Commitments   = null;
            if (_Hashes != null)
            {
                var commitments   = new ServerCommitment[_Hashes.Length][];
                var salts         = new uint256[_Hashes.Length][];
                var feeVariations = new Money[_Hashes.Length][];
                for (int i = 0; i < _Hashes.Length; i++)
                {
                    salts[i]         = new uint256[_Parameters.FakeTransactionCountPerLevel];
                    feeVariations[i] = new Money[_Parameters.RealTransactionCountPerLevel];
                    commitments[i]   = new ServerCommitment[_Hashes[i].Length];
                    int fakeJ = 0, realJ = 0;
                    for (int j = 0; j < _Hashes[i].Length; j++)
                    {
                        if (_Hashes[i][j] is FakeHash fake)
                        {
                            salts[i][fakeJ++] = fake.Salt;
                        }

                        if (_Hashes[i][j] is RealHash real)
                        {
                            feeVariations[i][realJ++] = real.FeeVariation;
                        }

                        commitments[i][j] = _Hashes[i][j].Commitment;
                    }
                }
                state.Salts         = salts;
                state.FeeVariations = feeVariations;
                state.Commitments   = commitments;
            }
            return(state);
        }