Created
September 28, 2021 10:47
-
-
Save MichalBrylka/229b77d14434f554961815480d81ce7c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Numerics; | |
using System.Security.Cryptography; | |
using NUnit.Framework; | |
using NUnit.Framework.Constraints; | |
namespace ProbablePrimeConstraintDemo | |
{ | |
[TestFixture] | |
class Program | |
{ | |
[Test] | |
public void SecurityNumber_ShouldBeSecure() | |
{ | |
var number = GenerateSecureNumber(); | |
Assert.Multiple(() => | |
{ | |
Assert.That(number, Is.Positive); | |
Assert.That(number, Is.GreaterThan(BigInteger.Pow(10, 22))); | |
Assert.That(number, ShouldBe.ProbablePrime.WithCertainty(100)); | |
//Assert.That(number+1, ShouldBe.ProbablePrime.WithCertainty(100)); | |
//Assert.That(2 + 2, Is.EqualTo(5)); | |
}); | |
} | |
private static BigInteger GenerateSecureNumber() => BigInteger.Parse("11111111111111111111111"); | |
} | |
public sealed class ShouldBe //: Is | |
{ | |
public static IsProbablePrimeConstraint ProbablePrime => new(); | |
} | |
public sealed class IsProbablePrimeConstraint : Constraint | |
{ | |
private ushort _certainty = 50; | |
public IsProbablePrimeConstraint WithCertainty(ushort certainty) | |
{ | |
if (certainty <= 2) throw new ArgumentOutOfRangeException(nameof(certainty)); | |
_certainty = certainty; | |
return this; | |
} | |
public IsProbablePrimeConstraint() => Description = "Probable Prime Number"; | |
public override ConstraintResult ApplyTo<TActual>(TActual actual) | |
=> new(this, actual, actual is BigInteger bi && IsProbablePrime(bi, _certainty)); | |
private static bool IsProbablePrime(BigInteger source, int certainty) | |
{ | |
if (source == 2 || source == 3) | |
return true; | |
if (source < 2 || source % 2 == 0) | |
return false; | |
BigInteger d = source - 1; | |
int s = 0; | |
while (d % 2 == 0) | |
{ | |
d /= 2; | |
s += 1; | |
} | |
var rng = RandomNumberGenerator.Create(); | |
byte[] bytes = new byte[source.ToByteArray().LongLength]; | |
for (int i = 0; i < certainty; i++) | |
{ | |
BigInteger a; | |
do | |
{ | |
rng.GetBytes(bytes); | |
a = new BigInteger(bytes); | |
} | |
while (a < 2 || a >= source - 2); | |
var x = BigInteger.ModPow(a, d, source); | |
if (x == 1 || x == source - 1) | |
continue; | |
for (int r = 1; r < s; r++) | |
{ | |
x = BigInteger.ModPow(x, 2, source); | |
if (x == 1) | |
return false; | |
if (x == source - 1) | |
break; | |
} | |
if (x != source - 1) | |
return false; | |
} | |
return true; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment