Add scalar random and remove extension.
MODIFY
WalletWasabi.Tests/UnitTests/Crypto/RandomTests.cs
WalletWasabi.Tests/UnitTests/Crypto/RandomTests.cs
+using NBitcoin.Secp256k1;
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
using WalletWasabi.Crypto.Randomness;
using WalletWasabi.Helpers;
@@ -31,8 +33,9 @@ namespace WalletWasabi.Tests.UnitTests.Crypto
var pseudoSet = new HashSet<byte[]>();
var secureSet = new HashSet<byte[]>();
var count = 100;
- var unsecureRandom = new UnsecureRandom();
- using var secureRandom = new SecureRandom();
+ IWasabiRandom unsecureRandom = new UnsecureRandom();
+ using var secureRandomToDispose = new SecureRandom();
+ IWasabiRandom secureRandom = secureRandomToDispose;
for (int i = 0; i < count; i++)
{
pseudoSet.Add(unsecureRandom.GetBytes(10));
@@ -72,5 +75,44 @@ namespace WalletWasabi.Tests.UnitTests.Crypto
}
}
}
+
+ [Fact]
+ public void ScalarTests()
+ {
+ // Make sure first that scalar equality works within hashset and that the underlying API won't pull the floor out.
+ var singleSet = new HashSet<Scalar>();
+ var scalar = new Scalar(5);
+ var same = new Scalar(5);
+ singleSet.Add(scalar);
+ singleSet.Add(same);
+ Assert.Single(singleSet);
+
+ var randoms = new List<IWasabiRandom>
+ {
+ new SecureRandom(),
+ new UnsecureRandom()
+ };
+
+ foreach (var random in randoms)
+ {
+ // It's probabilistically ensured that it never produces the same scalar, so unit test should pass always.
+ var nonZeroSet = new HashSet<Scalar>();
+ var count = 100;
+ for (int i = 0; i < count; i++)
+ {
+ Scalar randomScalar = random.GetScalarNonZero();
+ nonZeroSet.Add(randomScalar);
+ }
+ Assert.Equal(count, nonZeroSet.Count);
+
+ // Well, this is unlikely to catch any issues, but it catches the large ones at least.
+ Assert.True(nonZeroSet.All(x => x != Scalar.Zero));
+
+ if (random is SecureRandom secureRandom)
+ {
+ secureRandom.Dispose();
+ }
+ }
+ }
}
}

MODIFY
WalletWasabi/Crypto/Randomness/IWasabiRandom.cs
WalletWasabi/Crypto/Randomness/IWasabiRandom.cs
using NBitcoin;
+using NBitcoin.Secp256k1;
using System;
using System.Collections.Generic;
using System.Text;
@@ -8,5 +9,25 @@ namespace WalletWasabi.Crypto.Randomness
{
public interface IWasabiRandom : IRandom
{
+ public byte[] GetBytes(int length)
+ {
+ Guard.MinimumAndNotNull(nameof(length), length, 1);
+ var buffer = new byte[length];
+ GetBytes(buffer);
+ return buffer;
+ }
+
+ public Scalar GetScalarNonZero()
+ {
+ Scalar randomScalar;
+ int overflow;
+ Span<byte> buffer = stackalloc byte[32];
+ do
+ {
+ GetBytes(buffer);
+ randomScalar = new Scalar(buffer, out overflow);
+ } while (overflow != 0 || randomScalar.IsZero);
+ return randomScalar;
+ }
}
}

DELETE
WalletWasabi/Crypto/Randomness/IWasabiRandomExtensions.cs
-using System;
-using System.Collections.Generic;
-using System.Text;
-using WalletWasabi.Helpers;
-
-namespace WalletWasabi.Crypto.Randomness
-{
- public static class IWasabiRandomExtensions
- {
- public static byte[] GetBytes(this IWasabiRandom me, int length)
- {
- Guard.MinimumAndNotNull(nameof(length), length, 1);
- var buffer = new byte[length];
- me.GetBytes(buffer);
- return buffer;
- }
- }
-}

MODIFY
WalletWasabi/Crypto/Randomness/MockRandom.cs
WalletWasabi/Crypto/Randomness/MockRandom.cs
+using NBitcoin.Secp256k1;
using System;
using System.Collections.Generic;
using System.Text;

Add scalar random and remove extension.