Synthetic nonce vector size fixed to length of witness
Ensures that the witness is non empty and constrain the dimensions the returned
ScalarVectors in line with our current needs in the LinearRelation class,
namely having one blinding factor per secret component per equation.
MODIFY
WalletWasabi.Tests/UnitTests/Crypto/TranscriptTests.cs
WalletWasabi.Tests/UnitTests/Crypto/TranscriptTests.cs
using NBitcoin.Secp256k1;
+using System;
+using System.Linq;
using System.Text;
using WalletWasabi.Crypto.Groups;
using WalletWasabi.Crypto.Randomness;
@@ -139,5 +141,38 @@ namespace WalletWasabi.Tests.UnitTests.Crypto
// witness, with no randomness they should be identical
Assert.Equal(secretNonce3, secretNonce4);
}
+
+ [Theory]
+ [InlineData(1)]
+ [InlineData(3)]
+ [InlineData(5)]
+ [InlineData(7)]
+ public void SyntheticNoncesVectorTest(int size)
+ {
+ var protocol = Encoding.UTF8.GetBytes("witness size");
+
+ var rnd = new SecureRandom();
+
+ var witness = new Scalar[size];
+
+ var transcript = new Transcript(protocol);
+ var secretNonceProvider = transcript.CreateSyntheticSecretNonceProvider(witness, rnd);
+
+ var secretNonce = secretNonceProvider.Sequence.First();
+
+ Assert.Equal(secretNonce.Count(), witness.Length );
+ }
+
+ [Fact]
+ public void SyntheticNoncesThrows()
+ {
+ var protocol = Encoding.UTF8.GetBytes("empty witness not allowed");
+
+ var rnd = new SecureRandom();
+
+ var transcript = new Transcript(protocol);
+
+ Assert.ThrowsAny<ArgumentException>(() => transcript.CreateSyntheticSecretNonceProvider(new Scalar[0], rnd));
+ }
}
}

MODIFY
WalletWasabi/Crypto/ZeroKnowledge/SyntheticSecretNonceProvider.cs
WalletWasabi/Crypto/ZeroKnowledge/SyntheticSecretNonceProvider.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using WalletWasabi.Crypto.Randomness;
using WalletWasabi.Crypto.StrobeProtocol;
+using WalletWasabi.Helpers;
namespace WalletWasabi.Crypto.ZeroKnowledge
{
@@ -12,6 +13,8 @@ namespace WalletWasabi.Crypto.ZeroKnowledge
public SyntheticSecretNonceProvider(Strobe128 strobe, IEnumerable<Scalar> secrets, WasabiRandom random)
{
+ Guard.NotNullOrEmpty(nameof(secrets), secrets);
+
_strobe = strobe;
// add secret inputs as key material
@@ -20,21 +23,36 @@ namespace WalletWasabi.Crypto.ZeroKnowledge
_strobe.Key(secret.ToBytes(), false);
}
+ // add randomness as key material
_strobe.Key(random.GetBytes(32), false);
+
+ // Set up a generator of vectors of scalars the size as secrets vector
+ Sequence = VectorGenerator(secrets.Count());
+ }
+
+ public IEnumerable<ScalarVector> Sequence { get; }
+
+ public Scalar GetScalar()
+ {
+ return new Scalar(_strobe.Prf(32, false));
}
- public IEnumerable<Scalar> Sequence()
+ private IEnumerable<Scalar> ScalarGenerator()
{
while (true)
{
- yield return new Scalar(_strobe.Prf(32, false));
+ yield return GetScalar();
}
}
- public Scalar GetScalar() =>
- Sequence().First();
-
- public ScalarVector GetScalar(uint len) =>
- new ScalarVector(Sequence().Take((int)len));
+ private IEnumerable<ScalarVector> VectorGenerator(int len)
+ {
+ while (true)
+ {
+ // ScalarVector's constructor will call ToArray internally, hopefully
+ // minimizing copying
+ yield return new ScalarVector(ScalarGenerator().Take(len));
+ }
+ }
}
}

Synthetic nonce vector size fixed to length of witness

Ensures that the witness is non empty and constrain the dimensions the returned
ScalarVectors in line with our current needs in the LinearRelation class,
namely having one blinding factor per secret component per equation.