Take random zero check to random generator.
MODIFY
WalletWasabi/Crypto/Randomness/MockRandom.cs
WalletWasabi/Crypto/Randomness/MockRandom.cs
@@ -30,7 +30,7 @@ namespace WalletWasabi.Crypto.Randomness
throw new NotImplementedException();
}
- public override Scalar GetScalar()
+ public override Scalar GetScalar(bool allowZero = true)
{
if (GetScalarResults.Any())
{
@@ -40,7 +40,7 @@ namespace WalletWasabi.Crypto.Randomness
}
else
{
- return base.GetScalar();
+ return base.GetScalar(allowZero);
}
}
}

MODIFY
WalletWasabi/Crypto/Randomness/WasabiRandom.cs
WalletWasabi/Crypto/Randomness/WasabiRandom.cs
@@ -36,17 +36,24 @@ namespace WalletWasabi.Crypto.Randomness
return random;
}
- public virtual Scalar GetScalar()
+ public virtual Scalar GetScalar(bool allowZero = true)
{
Scalar randomScalar;
int overflow;
Span<byte> buffer = stackalloc byte[32];
+ var randomWasZero = false;
do
{
GetBytes(buffer);
randomScalar = new Scalar(buffer, out overflow);
+
+ if (randomScalar.IsZero && randomWasZero)
+ {
+ throw new InvalidOperationException("Random generator generated zero scalar twice in a row. Stop using this computer now!");
+ }
+ randomWasZero = randomScalar.IsZero;
}
- while (overflow != 0);
+ while (overflow != 0 || (!allowZero && randomScalar.IsZero));
return randomScalar;
}
}

MODIFY
WalletWasabi/Crypto/ZeroKnowledge/Prover.cs
WalletWasabi/Crypto/ZeroKnowledge/Prover.cs
@@ -82,33 +82,15 @@ namespace WalletWasabi.Crypto.ZeroKnowledge
try
{
- Scalar randomScalar = Scalar.Zero;
- var gotZero = false;
+ var scalar = random.GetScalar(allowZero: false);
+ // Sanity checks:
- while (randomScalar == Scalar.Zero)
+ if (scalar.IsOverflow || scalar.IsZero)
{
- randomScalar = random.GetScalar();
-
- // We can tolerate zero scalar only once.
- // Its probability is null to get it even once, but getting it twice is a catastrophe.
- if (randomScalar == Scalar.Zero)
- {
- if (gotZero)
- {
- throw new InvalidOperationException("Something is wrong with the random generation. It should not return zero scalar twice in a row.");
- }
- else
- {
- gotZero = true;
- }
- }
+ throw new InvalidOperationException("Bloody murder! Random generator served invalid scalar.");
}
- if (randomScalar.IsOverflow)
- {
- throw new InvalidOperationException("Something is wrong with the random generation. It should not return overflown scalar.");
- }
- return randomScalar;
+ return scalar;
}
finally
{

Take random zero check to random generator.