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)); }
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(); }
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); }
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); }
public static bool VerifyUnblindedSignature(this Signer signer, UnblindedSignature signature, uint256 dataHash) { return(VerifySignature(dataHash, signature, signer.Key.PubKey)); }
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)); }
/// <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)); }