Introduce tuple instead of accepting two separate enumerations
MODIFY
WalletWasabi.Tests/UnitTests/Crypto/ZeroKnowledge/KnowledgeOfRepresentationTests.cs
WalletWasabi.Tests/UnitTests/Crypto/ZeroKnowledge/KnowledgeOfRepresentationTests.cs
@@ -24,11 +24,15 @@ namespace WalletWasabi.Tests.UnitTests.Crypto.ZeroKnowledge
var secrets = new[] { new Scalar(scalarSeed1), new Scalar(scalarSeed2) };
var generators = new[] { Generators.G, Generators.Ga };
var publicPoint = GroupElement.Infinity;
+ var secretGeneratorPairs = new List<(Scalar, GroupElement)>();
for (int i = 0; i < secrets.Length; i++)
{
- publicPoint += secrets[i] * generators[i];
+ Scalar secret = secrets[i];
+ GroupElement generator = generators[i];
+ publicPoint += secret * generator;
+ secretGeneratorPairs.Add((secret, generator));
}
- var proof = Prover.CreateProof(secrets, publicPoint, generators);
+ var proof = Prover.CreateProof(secretGeneratorPairs, publicPoint);
Assert.True(Verifier.Verify(proof, publicPoint, generators));
}
}

MODIFY
WalletWasabi/Crypto/ZeroKnowledge/Challenge.cs
WalletWasabi/Crypto/ZeroKnowledge/Challenge.cs
@@ -23,7 +23,7 @@ namespace WalletWasabi.Crypto.ZeroKnowledge
return HashToScalar(publicPoint, nonce);
}
- public static Scalar HashToScalar(params GroupElement[] transcript)
+ public static Scalar HashToScalar(IEnumerable<GroupElement> transcript)
{
var concatenation = ByteHelpers.Combine(transcript.Select(x => x.ToBytes()));
using var sha256 = System.Security.Cryptography.SHA256.Create();
@@ -31,5 +31,8 @@ namespace WalletWasabi.Crypto.ZeroKnowledge
var challenge = new Scalar(hash);
return challenge;
}
+
+ public static Scalar HashToScalar(params GroupElement[] transcript)
+ => HashToScalar(transcript as IEnumerable<GroupElement>);
}
}

MODIFY
WalletWasabi/Crypto/ZeroKnowledge/Prover.cs
WalletWasabi/Crypto/ZeroKnowledge/Prover.cs
@@ -22,30 +22,19 @@ namespace WalletWasabi.Crypto.ZeroKnowledge
throw new InvalidOperationException($"{nameof(publicPoint)} != {nameof(secret)} * {nameof(generator)}");
}
- var proof = CreateProof(new[] { secret }, publicPoint, new[] { generator }, random);
+ var proof = CreateProof(new[] { (secret, generator) }, publicPoint, random);
return new KnowledgeOfExponent(proof.Nonce, proof.Responses.First());
}
- public static KnowledgeOfRepresentation CreateProof(IEnumerable<Scalar> secrets, GroupElement publicPoint, IEnumerable<GroupElement> generators, WasabiRandom? random = null)
+ public static KnowledgeOfRepresentation CreateProof(IEnumerable<(Scalar secret, GroupElement generator)> secretGeneratorPairs, GroupElement publicPoint, WasabiRandom? random = null)
{
Guard.False($"{nameof(publicPoint)}.{nameof(publicPoint.IsInfinity)}", publicPoint.IsInfinity);
- var secretArray = secrets.ToArray();
- var generatorArray = generators.ToArray();
-
- if (secretArray.Length != generatorArray.Length)
- {
- throw new ArgumentException($"Same number of secrets and generators must be provided. Secrets: {secretArray.Length}, Generators: {generatorArray.Length}");
- }
-
var nonce = GroupElement.Infinity;
var randomScalars = new List<Scalar>();
- for (int i = 0; i < secretArray.Length; i++)
+ foreach (var (secret, generator) in secretGeneratorPairs)
{
- var secret = secretArray[i];
- var generator = generatorArray[i];
-
Guard.False($"{nameof(secret)}.{nameof(secret.IsOverflow)}", secret.IsOverflow);
Guard.False($"{nameof(secret)}.{nameof(secret.IsZero)}", secret.IsZero);
Guard.False($"{nameof(generator)}.{nameof(generator.IsInfinity)}", generator.IsInfinity);
@@ -57,13 +46,15 @@ namespace WalletWasabi.Crypto.ZeroKnowledge
nonce += randomPoint;
}
- var challenge = Challenge.HashToScalar(new[] { publicPoint, nonce }.Concat(generators).ToArray());
+ var challenge = Challenge.HashToScalar(new[] { publicPoint, nonce }.Concat(secretGeneratorPairs.Select(x => x.generator)));
+ var secretArray = secretGeneratorPairs.Select(x => x.secret).ToArray();
+ var randomScalarArray = randomScalars.ToArray();
var responses = new List<Scalar>();
for (int i = 0; i < secretArray.Length; i++)
{
var secret = secretArray[i];
- var randomScalar = randomScalars.ToArray()[i];
+ var randomScalar = randomScalarArray[i];
var response = randomScalar + secret * challenge;
responses.Add(response);
}

Introduce tuple instead of accepting two separate enumerations