diff --git a/src/Aprismatic.PohligHellman/Aprismatic.PohligHellman.csproj b/src/Aprismatic.PohligHellman/Aprismatic.PohligHellman.csproj index 1ff4615..65fea81 100644 --- a/src/Aprismatic.PohligHellman/Aprismatic.PohligHellman.csproj +++ b/src/Aprismatic.PohligHellman/Aprismatic.PohligHellman.csproj @@ -4,6 +4,6 @@ Extension for the .NET Framework cryptography subsystem, which introduces the Pohlig-Hellman exponentiation cipher. - + \ No newline at end of file diff --git a/src/Aprismatic.PohligHellman/PohligHellman.cs b/src/Aprismatic.PohligHellman/PohligHellman.cs index 6add0d9..a2b5f11 100644 --- a/src/Aprismatic.PohligHellman/PohligHellman.cs +++ b/src/Aprismatic.PohligHellman/PohligHellman.cs @@ -19,13 +19,14 @@ public class PohligHellman : IDisposable public PohligHellman(int keySize) { _rng = RandomNumberGenerator.Create(); KeySize = keySize; - _keyStruct = CreateKeyPair(); + var p = BigInteger.One.GenPseudoPrime(KeySize, 16, _rng); + _keyStruct = CreateKeyPair(p); } - public PohligHellman(BigInteger P) { + public PohligHellman(BigInteger p) { _rng = RandomNumberGenerator.Create(); - KeySize = P.BitCount(); - _keyStruct = CreateKeyPair(P); + KeySize = p.BitCount(); + _keyStruct = CreateKeyPair(p); } // TODO: Consolidate constructors in one method @@ -42,11 +43,6 @@ public PohligHellman(PohligHellmanParameters prms) { public PohligHellman(string xml) : this(PohligHellmanParameters.FromXml(xml)) { } // TODO: This method should probably move to KeyStruct - private PohligHellmanKeyStruct CreateKeyPair() { - var P = BigInteger.One.GenPseudoPrime(KeySize, 16, _rng); - return CreateKeyPair(P); - } - private PohligHellmanKeyStruct CreateKeyPair(BigInteger P) { BigInteger E, D; var PminusOne = P - BigInteger.One; @@ -62,7 +58,7 @@ private PohligHellmanKeyStruct CreateKeyPair(BigInteger P) { public byte[] EncryptData(BigInteger message) { if (message < 0 || message > MaxEncryptableValue) - throw new ArgumentException($"Value should be 0 <= m <= {MaxEncryptableValue}", nameof(message)); + throw new ArgumentException($"Value should be 0 <= m <= {MaxEncryptableValue} under the current encryption key", nameof(message)); var ctbs = _keyStruct.CiphertextLength; var array = new byte[ctbs]; diff --git a/test/PohligHellmanTests/MainTests.cs b/test/PohligHellmanTests/MainTests.cs new file mode 100644 index 0000000..0ef7947 --- /dev/null +++ b/test/PohligHellmanTests/MainTests.cs @@ -0,0 +1,57 @@ +using System; +using System.Numerics; +using System.Security.Cryptography; +using Aprismatic; +using Aprismatic.PohligHellman; +using Xunit; +using Xunit.Abstractions; + +namespace PohligHellmanTests +{ + public class MainTests : IDisposable + { + private readonly ITestOutputHelper _output; + + private readonly Random _rnd = new(); + private readonly RandomNumberGenerator _rng = RandomNumberGenerator.Create(); + + public MainTests(ITestOutputHelper output) { + _output = output; + } + + public void Dispose() { + _rng.Dispose(); + } + + [Fact(DisplayName = "Correctness")] + public void TestCorrectness() { + for (var i = 0; i < Globals.Iterations; i++) { + var ks = _rnd.Next(Globals.MinKeyLength, Globals.MaxKeyLength); + using var algorithm = new PohligHellman(ks); + + Assert.Equal(ks, algorithm.KeySize); + + var o = BigInteger.Zero.GenRandomBits(1, BigInteger.Pow(2, algorithm.KeySize - 1) - 1, _rng); + + var o_enc = algorithm.EncryptData(o); + var o_dec = algorithm.DecryptData(o_enc); + + Assert.Equal(o, o_dec); + } + + for (var i = 0; i < Globals.Iterations; i++) { + var p = BigInteger.One.GenPseudoPrime(_rnd.Next(Globals.MinKeyLength, Globals.MaxKeyLength), 16, _rng); + using var algorithm = new PohligHellman(p); + + Assert.Equal(p, algorithm.P); + + var o = BigInteger.Zero.GenRandomBits(1, BigInteger.Pow(2, algorithm.KeySize - 1) - 1, _rng); + + var o_enc = algorithm.EncryptData(o); + var o_dec = algorithm.DecryptData(o_enc); + + Assert.Equal(o, o_dec); + } + } + } +}