예제 #1
0
        public void CanBlindSign()
        {
            // Generate ECDSA keypairs.
            var    r      = new Key();
            var    key    = new Key();
            Signer signer = new Signer(key, r);

            // Generate ECDSA requester.
            // Get the r's pubkey and the key's pubkey.
            // Blind messages.
            Requester requester = new Requester();
            PubKey    rPubKey   = r.PubKey;
            PubKey    keyPubKey = key.PubKey;

            byte[]  message            = Encoding.UTF8.GetBytes("áéóúősing me please~!@#$%^&*())_+");
            byte[]  hashBytes          = Hashes.SHA256(message);
            uint256 hash               = new uint256(hashBytes);
            uint256 blindedMessageHash = requester.BlindMessage(hash, rPubKey, keyPubKey);

            // Sign the blinded message hash.
            uint256 blindedSignature = signer.Sign(blindedMessageHash);

            // Unblind the signature.
            UnblindedSignature unblindedSignature = requester.UnblindSignature(blindedSignature);

            // verify the original data is signed

            Assert.True(VerifySignature(hash, unblindedSignature, keyPubKey));
        }
예제 #2
0
        public void CanParseUnblindedSignature()
        {
            var requester = new Requester();

            using var r   = new Key(Encoders.Hex.DecodeData("31E151628AED2A6ABF7155809CF4F3C762E7160F38B4DA56B784D9045190CFA0"));
            using var key = new Key(Encoders.Hex.DecodeData("B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF"));
            var signer = new Signer(key);

            var message            = new uint256(Encoders.Hex.DecodeData("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"), false);
            var blindedMessage     = requester.BlindMessage(message, r.PubKey, key.PubKey);
            var blindSignature     = signer.Sign(blindedMessage, r);
            var unblindedSignature = requester.UnblindSignature(blindSignature);

            var str = unblindedSignature.ToString();

            Assert.True(UnblindedSignature.TryParse(str, out var unblindedSignature2));
            Assert.Equal(unblindedSignature.C, unblindedSignature2 !.C);
            Assert.Equal(unblindedSignature.S, unblindedSignature2.S);
            str += "o";
            Assert.False(UnblindedSignature.TryParse(str, out _));
            Assert.Throws <FormatException>(() => UnblindedSignature.Parse(str));
            byte[] overflow = new byte[64];
            overflow.AsSpan().Fill(255);
            Assert.False(UnblindedSignature.TryParse(overflow, out _));
            Assert.Throws <FormatException>(() => UnblindedSignature.Parse(overflow));
        }
        /// <inheritdoc />
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            UnblindedSignature signature = (UnblindedSignature)value;

            writer.WriteStartArray();
            writer.WriteValue(signature.C.ToString());
            writer.WriteValue(signature.S.ToString());
            writer.WriteEndArray();
        }
예제 #4
0
        public async Task <(RoundPhase currentPhase, IEnumerable <ActiveOutput> activeOutputs)> PostConfirmationAsync()
        {
            using HttpResponseMessage response = await TorClient.SendAsync(HttpMethod.Post, $"/api/v{Helpers.Constants.BackendMajorVersion}/btc/chaumiancoinjoin/confirmation?uniqueId={UniqueId}&roundId={RoundId}").ConfigureAwait(false);

            if (response.StatusCode != HttpStatusCode.OK)
            {
                await response.ThrowRequestExceptionFromContentAsync().ConfigureAwait(false);
            }

            ConnectionConfirmationResponse resp = await response.Content.ReadAsJsonAsync <ConnectionConfirmationResponse>().ConfigureAwait(false);

            Logger.LogInfo($"Round ({RoundId}), Alice ({UniqueId}): Confirmed connection. Phase: {resp.CurrentPhase}.");

            var activeOutputs = new List <ActiveOutput>();

            if (resp.BlindedOutputSignatures != null && resp.BlindedOutputSignatures.Any())
            {
                var unblindedSignatures = new List <UnblindedSignature>();
                var blindedSignatures   = resp.BlindedOutputSignatures.ToArray();
                for (int i = 0; i < blindedSignatures.Length; i++)
                {
                    uint256            blindedSignature   = blindedSignatures[i];
                    Requester          requester          = Requesters[i];
                    UnblindedSignature unblindedSignature = requester.UnblindSignature(blindedSignature);

                    var address = RegisteredAddresses[i];

                    uint256 outputScriptHash = new uint256(Hashes.SHA256(address.ScriptPubKey.ToBytes()));
                    PubKey  signerPubKey     = SchnorrPubKeys[i].SignerPubKey;
                    if (!VerifySignature(outputScriptHash, unblindedSignature, signerPubKey))
                    {
                        throw new NotSupportedException($"Coordinator did not sign the blinded output properly for level: {i}.");
                    }

                    unblindedSignatures.Add(unblindedSignature);
                }

                for (int i = 0; i < Math.Min(unblindedSignatures.Count, RegisteredAddresses.Length); i++)
                {
                    var sig  = unblindedSignatures[i];
                    var addr = RegisteredAddresses[i];
                    var lvl  = i;

                    var actOut = new ActiveOutput(addr, sig, lvl);
                    activeOutputs.Add(actOut);
                }
            }

            return(resp.CurrentPhase, activeOutputs);
        }
    /// <inheritdoc />
    public override object ReadJson(JsonReader reader, Type?objectType, object?existingValue, JsonSerializer?serializer)
    {
        JArray arr = JArray.Load(reader);

        var carr = ToFixedLengthByteArray(StringToBigInteger(arr[0].Value <string>()));
        var sarr = ToFixedLengthByteArray(StringToBigInteger(arr[1].Value <string>()));

        var signatureBytes = carr.Concat(sarr).ToArray();
        var signature      = ByteHelpers.ToHex(signatureBytes);

        var sig = UnblindedSignature.Parse(signature);

        return(sig);
    }
    public static bool VerifySignature(uint256 message, UnblindedSignature signature, PubKey signerPubKey)
    {
        if (!Context.Instance.TryCreatePubKey(signerPubKey.ToBytes(), out var signerECPubkey))
        {
            throw new FormatException("Invalid signer pubkey.");
        }

        var p = signerECPubkey.Q;

        var sG = (signature.S * EC.G).ToGroupElement();
        var cP = p * signature.C;
        var r  = cP + sG;
        var t  = r.ToGroupElement().x.Normalize();

        using var sha = new SHA256();
        Span <byte> tmp = stackalloc byte[32];

        message.ToBytes(tmp, false);
        sha.Write(tmp);
        t.WriteToSpan(tmp);
        sha.Write(tmp);
        sha.GetHash(tmp);
        return(new Scalar(tmp) == signature.C);
    }
예제 #7
0
 public ActiveOutput(BitcoinAddress address, UnblindedSignature signature, int mixingLevel)
 {
     Address     = Guard.NotNull(nameof(address), address);
     Signature   = Guard.NotNull(nameof(signature), signature);
     MixingLevel = Guard.MinimumAndNotNull(nameof(mixingLevel), mixingLevel, 0);
 }
예제 #8
0
 public static bool VerifyUnblindedSignature(this Signer signer, UnblindedSignature signature, uint256 dataHash)
 {
     return(VerifySignature(dataHash, signature, signer.Key.PubKey));
 }
예제 #9
0
        public static bool VerifyUnblindedSignature(this Signer signer, UnblindedSignature signature, byte[] data)
        {
            uint256 hash = new uint256(Hashes.SHA256(data));

            return(VerifySignature(hash, signature, signer.Key.PubKey));
        }
예제 #10
0
        /// <returns>If the phase is still in OutputRegistration.</returns>
        public async Task <bool> PostOutputAsync(long roundId, BitcoinAddress activeOutputAddress, UnblindedSignature unblindedSignature, int level)
        {
            Guard.MinimumAndNotNull(nameof(roundId), roundId, 0);
            Guard.NotNull(nameof(activeOutputAddress), activeOutputAddress);
            Guard.NotNull(nameof(unblindedSignature), unblindedSignature);
            Guard.MinimumAndNotNull(nameof(level), level, 0);

            var request = new OutputRequest {
                OutputAddress = activeOutputAddress, UnblindedSignature = unblindedSignature, Level = level
            };

            using (var response = await TorClient.SendAsync(HttpMethod.Post, $"/api/v{Constants.BackendMajorVersion}/btc/chaumiancoinjoin/output?roundId={roundId}", request.ToHttpStringContent()))
            {
                if (response.StatusCode == HttpStatusCode.Conflict)
                {
                    return(false);
                }
                else if (response.StatusCode != HttpStatusCode.NoContent)
                {
                    await response.ThrowRequestExceptionFromContentAsync();
                }

                return(true);
            }
        }
        public bool VerifyUnblindedSignature(UnblindedSignature signature, byte[] data)
        {
            var hash = new uint256(Hashes.SHA256(data));

            return(VerifySignature(hash, signature, Key.PubKey));
        }