public static async Task <BigInteger> GenerateAsync(BigInteger maxExclusive, IRandomProvider randomProvider) { if (randomProvider == null) { throw new ArgumentNullException(nameof(randomProvider)); } if (maxExclusive == BigIntegerHelpers.Zero) { throw new ArgumentOutOfRangeException(nameof(maxExclusive), "Max exclusive must be above 0."); } if (maxExclusive == BigIntegerHelpers.One) { return(BigInteger.Zero); } if (maxExclusive < new BigInteger(int.MaxValue)) { return(new BigInteger(randomProvider.NextInt((int)maxExclusive))); } var bytes = maxExclusive.ToByteArray(); BigInteger result = 0; await Task.Run(() => { do { randomProvider.NextBytes(bytes); if (bytes.All(v => v == 0)) { throw new InvalidOperationException("Zero buffer returned by random provider."); } bytes[bytes.Length - 1] &= 0x7F; result = new BigInteger(bytes); } while (result >= maxExclusive || result.Equals(BigIntegerHelpers.One) || result.Equals(BigIntegerHelpers.Zero)); }); return(result); }
public static async Task <BigInteger> GeneratePrime(uint bitLength, IRandomProvider randomProvider, IPrimalityTest primalityTest) { if (randomProvider == null) { throw new ArgumentNullException(nameof(randomProvider)); } if (bitLength < 8) { throw new ArgumentOutOfRangeException(nameof(bitLength), "Bit length must be at least of length 8."); } var bytes = bitLength / 8; var randomNumberBytes = new byte[bytes]; randomProvider.NextBytes(randomNumberBytes); var result = new BigInteger(randomNumberBytes); if (result.Sign < 0) { result = BigInteger.Negate(result); } if (result.IsEven) { result = result + 1; } while (!await primalityTest.TestAsync(result)) { result = result + 2; } return(result); }