diff --git a/src/Aprismatic.PaillierExt/Aprismatic.PaillierExt.csproj b/src/Aprismatic.PaillierExt/Aprismatic.PaillierExt.csproj index 996ed15..67831cf 100644 --- a/src/Aprismatic.PaillierExt/Aprismatic.PaillierExt.csproj +++ b/src/Aprismatic.PaillierExt/Aprismatic.PaillierExt.csproj @@ -1,11 +1,11 @@  - netstandard2.0 + netstandard2.1 Extension for the .NET Framework cryptography subsystem, which introduces the Paillier public key cryptosystem with support for homomorphic addition. - - + + diff --git a/src/Aprismatic.PaillierExt/Paillier.cs b/src/Aprismatic.PaillierExt/Paillier.cs index 53a483c..32cbf6e 100644 --- a/src/Aprismatic.PaillierExt/Paillier.cs +++ b/src/Aprismatic.PaillierExt/Paillier.cs @@ -7,105 +7,129 @@ namespace Aprismatic.PaillierExt { - public class Paillier : AsymmetricAlgorithm + public class Paillier : AsymmetricAlgorithm, IDisposable { - private PaillierKeyStruct keyStruct; + private readonly PaillierKeyStruct keyStruct; + private readonly PaillierEncryptor encryptor; + private readonly PaillierDecryptor decryptor; - public PaillierKeyStruct KeyStruct + public Paillier(int keySize) { - get - { - if (NeedToGenerateKey()) - { - CreateKeyPair(KeySizeValue); - } - return keyStruct; - } - set => keyStruct = value; + LegalKeySizesValue = new[] { new KeySizes(384, 1088, 8) }; + KeySizeValue = keySize; + keyStruct = CreateKeyPair(); + encryptor = new PaillierEncryptor(keyStruct); + decryptor = new PaillierDecryptor(keyStruct); } - public Paillier() + public Paillier(PaillierParameters prms) { - keyStruct = new PaillierKeyStruct - { - N = BigInteger.Zero, - G = BigInteger.Zero, - Lambda = BigInteger.Zero, - Miu = BigInteger.Zero - }; + LegalKeySizesValue = new[] { new KeySizes(384, 1088, 8) }; - // set the default key size value - KeySizeValue = 384; + keyStruct = new PaillierKeyStruct( + new BigInteger(prms.N), + new BigInteger(prms.G), + (prms.Lambda?.Length ?? 0) > 0 ? new BigInteger(prms.Lambda) : BigInteger.Zero, + (prms.Miu?.Length ?? 0) > 0 ? new BigInteger(prms.Miu) : BigInteger.Zero + ); - // set the range of legal keys - LegalKeySizesValue = new[] { new KeySizes(384, 1088, 8) }; + KeySizeValue = keyStruct.NLength * 8; + + encryptor = new PaillierEncryptor(keyStruct); + decryptor = new PaillierDecryptor(keyStruct); } - private bool NeedToGenerateKey() + public Paillier(string Xml) { - return keyStruct.N == 0 - && keyStruct.G == 0; + LegalKeySizesValue = new[] { new KeySizes(384, 1088, 8) }; + + var prms = new PaillierParameters(); + var keyValues = XDocument.Parse(Xml).Element("PaillierKeyValue"); + prms.N = Convert.FromBase64String((String) keyValues.Element("N") ?? ""); + prms.G = Convert.FromBase64String((String) keyValues.Element("G") ?? ""); + prms.Lambda = Convert.FromBase64String((String) keyValues.Element("Lambda") ?? ""); + prms.Miu = Convert.FromBase64String((String) keyValues.Element("Miu") ?? ""); + + keyStruct = new PaillierKeyStruct( + new BigInteger(prms.N), + new BigInteger(prms.G), + new BigInteger(prms.Lambda), + new BigInteger(prms.Miu) + ); + + KeySizeValue = keyStruct.NLength * 8; + + encryptor = new PaillierEncryptor(keyStruct); + decryptor = new PaillierDecryptor(keyStruct); } + public int MaxPlaintextBits() => PaillierKeyStruct.MaxPlaintextBits; + public BigInteger PlaintextExp => PaillierKeyStruct.PlaintextExp; + public int GetPlaintextDecPlace() => PaillierKeyStruct.PlaintextDecPlace; + // TODO: check again for Miu - private void CreateKeyPair(int pKeyStrength) + private PaillierKeyStruct CreateKeyPair() { + BigInteger N, Lambda, G, Miu; + // create the large prime number, p and q - // p and q are assumed to have the same bit length (512 bit each, so that N is 1024) - // if N length is not the same to KeySize, will regenerate p and q which will make a new N - using (var rng = RandomNumberGenerator.Create()) + // p and q are assumed to have the same bit length (e.g., 192 bit each, so that N is 384) + // if N length is not the same to keySize, will regenerate p and q which will make a new N + using var rng = RandomNumberGenerator.Create(); + var p = new BigInteger(); + var q = new BigInteger(); + var halfKeyStrength = KeySizeValue >> 1; // div 2 + do { - var p = new BigInteger(); - var q = new BigInteger(); - do - { - p = p.GenPseudoPrime(pKeyStrength / 2, 16, rng); - q = q.GenPseudoPrime(pKeyStrength / 2, 16, rng); - - // compute N - // N = p*q - keyStruct.N = p * q; - } while (KeyStruct.getNLength() != pKeyStrength / 8); - - // compute G - // First option: g is random in Z*(n^2) - - // Second option: g = n + 1 - keyStruct.G = keyStruct.N + 1; - - // compute lambda - // lambda = lcm(p-1, q-1) = (p-1)*(q-1)/gcd(p-1, q-1) - // or simpler variant, lambda = (p-1)(q-1), since p and q have same length - keyStruct.Lambda = (p - 1) * (q - 1); - - // Miu = (L(g^lambda mod NSq))^-1 mod n - // or simple: Miu = lambda^-1 (mod n) - keyStruct.Miu = keyStruct.Lambda.ModInverse(keyStruct.N); - } + p = p.GenPseudoPrime(halfKeyStrength, 16, rng); + q = q.GenPseudoPrime(halfKeyStrength, 16, rng); + + // compute N + // N = p*q + N = p * q; + } while (N.BitCount() < KeySizeValue - 7); + + // compute G + // First option: G is random in Z*(N^2) + // Second option: G = N + 1 + G = N + 1; + + // compute lambda + // lambda = lcm(p-1, q-1) = (p-1)*(q-1)/gcd(p-1, q-1) + // or simpler variant, lambda = (p-1)(q-1), since p and q have same length + Lambda = (p - 1) * (q - 1); + + // Miu = (L(g^lambda mod NSq))^-1 mod n + // or simple: Miu = lambda^-1 (mod n) + Miu = Lambda.ModInverse(N); + + return new PaillierKeyStruct(N, G, Lambda, Miu); } - public byte[] EncryptData(BigFraction message) + public byte[] EncryptDataOld(BigFraction message) { - if (NeedToGenerateKey()) - { - CreateKeyPair(KeySizeValue); - } - using (var encryptor = new PaillierEncryptor(keyStruct)) { - return encryptor.ProcessBigInteger(message); + return encryptor.ProcessBigIntegerOld(message); } } - public BigFraction DecryptData(byte[] p_data) + public byte[] EncryptData(BigFraction message) { - if (NeedToGenerateKey()) - { - CreateKeyPair(KeySizeValue); - } + var res = new byte[keyStruct.CiphertextBlocksize * 2]; + encryptor.ProcessBigInteger(message, res.AsSpan()); + return res; + } + public BigFraction DecryptDataOld(byte[] p_data) + { var decryptor = new PaillierDecryptor(keyStruct); + return decryptor.ProcessByteBlockOld(p_data); + } + + public BigFraction DecryptData(byte[] p_data) + { return decryptor.ProcessByteBlock(p_data); } @@ -140,53 +164,12 @@ public override string ToXmlString(bool includePrivateParameters) return sb.ToString(); } - public override void FromXmlString(string str) - { - var prms = new PaillierParameters(); - - var keyValues = XDocument.Parse(str).Element("PaillierKeyValue"); - - prms.N = Convert.FromBase64String((String)keyValues.Element("N") ?? ""); - prms.G = Convert.FromBase64String((String)keyValues.Element("G") ?? ""); - prms.Lambda = Convert.FromBase64String((String)keyValues.Element("Lambda") ?? ""); - prms.Miu = Convert.FromBase64String((String)keyValues.Element("Miu") ?? ""); - - ImportParameters(prms); - } - - public void ImportParameters(PaillierParameters parameters) - { - keyStruct.N = new BigInteger(parameters.N); - keyStruct.G = new BigInteger(parameters.G); - - if (parameters.Lambda != null - && parameters.Lambda.Length > 0 - && parameters.Miu != null - && parameters.Miu.Length > 0) - { - keyStruct.Lambda = new BigInteger(parameters.Lambda); - keyStruct.Miu = new BigInteger(parameters.Miu); - } - else - { - keyStruct.Lambda = BigInteger.Zero; - keyStruct.Miu = BigInteger.Zero; - } - - KeySizeValue = keyStruct.N.BitCount(); - } - public PaillierParameters ExportParameters(bool includePrivateParams) { - if (NeedToGenerateKey()) - { - CreateKeyPair(KeySizeValue); - } - var prms = new PaillierParameters { N = keyStruct.N.ToByteArray(), - G = keyStruct.G.ToByteArray(), + G = keyStruct.G.ToByteArray() }; // if required, include the private value, X @@ -204,5 +187,10 @@ public PaillierParameters ExportParameters(bool includePrivateParams) return prms; } + + public new void Dispose() + { + encryptor.Dispose(); + } } } diff --git a/src/Aprismatic.PaillierExt/PaillierAbstractCipher.cs b/src/Aprismatic.PaillierExt/PaillierAbstractCipher.cs deleted file mode 100644 index bb3eb96..0000000 --- a/src/Aprismatic.PaillierExt/PaillierAbstractCipher.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Aprismatic.PaillierExt -{ - public abstract class PaillierAbstractCipher - { - protected readonly int CiphertextBlocksize; - protected PaillierKeyStruct KeyStruct; - - public PaillierAbstractCipher(PaillierKeyStruct keyStruct) - { - KeyStruct = keyStruct; - CiphertextBlocksize = keyStruct.getCiphertextBlocksize(); - } - } -} diff --git a/src/Aprismatic.PaillierExt/PaillierDecryptor.cs b/src/Aprismatic.PaillierExt/PaillierDecryptor.cs index 69a6583..efb0cf6 100644 --- a/src/Aprismatic.PaillierExt/PaillierDecryptor.cs +++ b/src/Aprismatic.PaillierExt/PaillierDecryptor.cs @@ -3,13 +3,16 @@ namespace Aprismatic.PaillierExt { - public class PaillierDecryptor : PaillierAbstractCipher + public class PaillierDecryptor { + private readonly PaillierKeyStruct _keyStruct; + public PaillierDecryptor(PaillierKeyStruct keyStruct) - : base(keyStruct) - { } + { + _keyStruct = keyStruct; + } - public BigFraction ProcessByteBlock(byte[] block) + public BigFraction ProcessByteBlockOld(byte[] block) { var block_half = new byte[block.Length / 2]; Array.Copy(block, block_half, block.Length / 2); @@ -17,17 +20,29 @@ public BigFraction ProcessByteBlock(byte[] block) // calculate M // m = (c^lambda(mod nsquare) - 1) / n * miu (mod n) - var m = (BigInteger.ModPow(bBlock, KeyStruct.Lambda, KeyStruct.NSquare) - 1) / KeyStruct.N * KeyStruct.Miu % KeyStruct.N; + var m = (BigInteger.ModPow(bBlock, _keyStruct.Lambda, _keyStruct.NSquare) - 1) / _keyStruct.N * _keyStruct.Miu % _keyStruct.N; + + return Decode(m); + } + + public BigFraction ProcessByteBlock(byte[] block) + { + var bBlock = new BigInteger(block.AsSpan(0, block.Length >> 1)); // div 2 + + // calculate M + // m = (c^lambda(mod nsquare) - 1) / n * miu (mod n) + var L = (BigInteger.ModPow(bBlock, _keyStruct.Lambda, _keyStruct.NSquare) - BigInteger.One) / _keyStruct.N; + var m = L * _keyStruct.Miu % _keyStruct.N; return Decode(m); } private BigFraction Decode(BigInteger n) { - var a = new BigFraction(n, KeyStruct.PlaintextExp); - a = a % (KeyStruct.MaxRawPlaintext + 1); - if ( a > KeyStruct.MaxRawPlaintext / 2) - a = a - KeyStruct.MaxRawPlaintext - 1; + var a = new BigFraction(n, PaillierKeyStruct.PlaintextExp); + a %= (PaillierKeyStruct.MaxRawPlaintext + 1); + if (a > PaillierKeyStruct.MaxEncryptableValue) + a = a - PaillierKeyStruct.MaxRawPlaintext - BigInteger.One; return a; } } diff --git a/src/Aprismatic.PaillierExt/PaillierEncryptor.cs b/src/Aprismatic.PaillierExt/PaillierEncryptor.cs index 9a39ac6..95f3569 100644 --- a/src/Aprismatic.PaillierExt/PaillierEncryptor.cs +++ b/src/Aprismatic.PaillierExt/PaillierEncryptor.cs @@ -4,58 +4,90 @@ namespace Aprismatic.PaillierExt { - public class PaillierEncryptor : PaillierAbstractCipher, IDisposable + public class PaillierEncryptor : IDisposable { - private RandomNumberGenerator rng; + private readonly RandomNumberGenerator rng; + private readonly PaillierKeyStruct _keyStruct; public PaillierEncryptor(PaillierKeyStruct keyStruct) - : base(keyStruct) { rng = RandomNumberGenerator.Create(); + _keyStruct = keyStruct; } - public byte[] ProcessBigInteger(BigFraction message) + public byte[] ProcessBigIntegerOld(BigFraction message) { - if (message.Denominator > KeyStruct.PlaintextExp) + if (message.Denominator > PaillierKeyStruct.PlaintextExp) { - BigInteger denominator = KeyStruct.PlaintextExp; + BigInteger denominator = PaillierKeyStruct.PlaintextExp; BigInteger numerator = message.Numerator * denominator / message.Denominator; message = new BigFraction(numerator, denominator); } - if (BigInteger.Abs(message.Numerator) > KeyStruct.MaxEncryptableValue) - throw new ArgumentException($"Numerator to encrypt is too large. Message should be |m| < 2^{KeyStruct.getMaxPlaintextBits() - 1}"); + if (BigInteger.Abs(message.Numerator) > PaillierKeyStruct.MaxEncryptableValue) + throw new ArgumentException($"Numerator to encrypt is too large. Message should be |m| < 2^{PaillierKeyStruct.MaxPlaintextBits - 1}"); // generate random R var R = new BigInteger(); - R = R.GenRandomBits(KeyStruct.N.BitCount() - 1, rng); // R's bitlength is n-1 so that r is within Zn + R = R.GenRandomBits(_keyStruct.N.BitCount() - 1, rng); // R's bitlength is n-1 so that r is within Zn // ciphertext c = g^m * r^n mod n^2 - var RN = BigInteger.ModPow(R, KeyStruct.N, KeyStruct.NSquare); + var RN = BigInteger.ModPow(R, _keyStruct.N, _keyStruct.NSquare); // if we use simple key generation (g = n + 1), we can use // (n+1)^m = n*m + 1 mod n^2 - var Gm = (KeyStruct.N * Encode(message) + 1) % KeyStruct.NSquare; - var Gm_Neg = (KeyStruct.N * Encode(-message) + 1) % KeyStruct.NSquare; + var Gm = (_keyStruct.N * Encode(message) + 1) % _keyStruct.NSquare; + var Gm_Neg = (_keyStruct.N * Encode(-message) + 1) % _keyStruct.NSquare; - var C = (Gm * RN) % KeyStruct.NSquare; - var C_Neg = (Gm_Neg * RN) % KeyStruct.NSquare; + var C = (Gm * RN) % _keyStruct.NSquare; + var C_Neg = (Gm_Neg * RN) % _keyStruct.NSquare; - var res = new byte[CiphertextBlocksize * 2]; + var res = new byte[_keyStruct.CiphertextBlocksize * 2]; var c_bytes = C.ToByteArray(); var c_Neg_bytes = C_Neg.ToByteArray(); Array.Copy(c_bytes, 0, res, 0, c_bytes.Length); - Array.Copy(c_Neg_bytes, 0, res, CiphertextBlocksize, c_Neg_bytes.Length); + Array.Copy(c_Neg_bytes, 0, res, _keyStruct.CiphertextBlocksize, c_Neg_bytes.Length); return res; } + public void ProcessBigInteger(BigFraction message, Span res) + { + if (message.Denominator > PaillierKeyStruct.PlaintextExp) + { + var denominator = PaillierKeyStruct.PlaintextExp; + var numerator = message.Numerator * denominator / message.Denominator; + message = new BigFraction(numerator, denominator); + } + + if (BigInteger.Abs(message.Numerator) > PaillierKeyStruct.MaxEncryptableValue) + throw new ArgumentException($"Numerator to encrypt is too large. Message should be |m| < 2^{PaillierKeyStruct.MaxPlaintextBits - 1}"); + + // generate random R + var R = BigInteger.Zero.GenRandomBits(_keyStruct.NBitCount - 1, rng); // R's bitlength is n-1 so that r is within Zn + + // ciphertext c = g^m * r^n mod n^2 + var RN = BigInteger.ModPow(R, _keyStruct.N, _keyStruct.NSquare); + + // if we use simple key generation (g = n + 1), we can use + // (n+1)^m = n*m + 1 mod n^2 + var Gm = (_keyStruct.N * Encode(message) + 1) % _keyStruct.NSquare; + var Gm_Neg = (_keyStruct.N * Encode(-message) + 1) % _keyStruct.NSquare; + + var C = (Gm * RN) % _keyStruct.NSquare; + var C_Neg = (Gm_Neg * RN) % _keyStruct.NSquare; + + var lgth = res.Length >> 1; + C.TryWriteBytes(res.Slice(0, lgth), out _); + C_Neg.TryWriteBytes(res.Slice(lgth, lgth), out _); + } + private BigInteger Encode(BigFraction a) { if (a < 0) - a = a + KeyStruct.MaxRawPlaintext + 1; - a = a * KeyStruct.PlaintextExp; + a = a + PaillierKeyStruct.MaxRawPlaintext + BigInteger.One; + a *= PaillierKeyStruct.PlaintextExp; return a.ToBigInteger(); } diff --git a/src/Aprismatic.PaillierExt/PaillierKeyStruct.cs b/src/Aprismatic.PaillierExt/PaillierKeyStruct.cs index bf92a19..c6bc759 100644 --- a/src/Aprismatic.PaillierExt/PaillierKeyStruct.cs +++ b/src/Aprismatic.PaillierExt/PaillierKeyStruct.cs @@ -4,85 +4,42 @@ namespace Aprismatic.PaillierExt { public struct PaillierKeyStruct { - private BigInteger _n; + public readonly BigInteger N; + public readonly BigInteger G; + public readonly BigInteger Lambda; + public readonly BigInteger Miu; - public BigInteger N + public PaillierKeyStruct(BigInteger n, BigInteger g, BigInteger lambda, BigInteger miu) { - get => _n; - set - { - _n = value; - NSquare = _n * _n; - } - } - public BigInteger NSquare { get; private set; } - - public BigInteger G; - public BigInteger Lambda; - public BigInteger Miu; + N = n; + NSquare = n * n; + NBitCount = n.BitCount(); + NLength = (NBitCount + 7) >> 3; // div 8 + NSquareLength = NLength * 2; - private BigInteger _maxRawPT; - public BigInteger MaxRawPlaintext - { - get - { - if (_maxRawPT == BigInteger.Zero) - _maxRawPT = BigInteger.Pow(2, getMaxPlaintextBits()) - BigInteger.One; - return _maxRawPT; - } - } + G = g; - private BigInteger _maxRawPT_half; - public BigInteger MaxEncryptableValue - { - get - { - if (_maxRawPT_half == BigInteger.Zero) - _maxRawPT_half = MaxRawPlaintext / 2; - return _maxRawPT_half; - } - } + Lambda = lambda; + Miu = miu; - private BigInteger _PTExp; - public BigInteger PlaintextExp - { - get - { - if (_PTExp == BigInteger.Zero) - _PTExp = BigInteger.Pow(10, getPlaintextDecPlace()); - return _PTExp; - } + CiphertextBlocksize = NLength * 2 + 2; // We add 2 because last bit of a BigInteger is reserved to store its sign. + CiphertextLength = CiphertextBlocksize * 2; // Therefore, theoretically, each part of ciphertext might need an extra byte to hold that one bit } - public int getMaxPlaintextBits() - { - return 128; // 128 bit - } + public const int MaxPlaintextBits = 128; + public const int PlaintextDecPlace = 12; // 12 decimal places allowed in plain text + public static readonly BigInteger PlaintextExp = BigInteger.Pow(10, PlaintextDecPlace); - public int getPlaintextDecPlace() - { - return 12; // 12 decimal places allowed in plain text - } + public static readonly BigInteger MaxRawPlaintext = BigInteger.Pow(2, MaxPlaintextBits) - BigInteger.One; + public static readonly BigInteger MaxEncryptableValue = MaxRawPlaintext >> 1; - public int getCiphertextBlocksize() - { - return getNLength() * 2 + 2; - } - - public int getCiphertextLength() - { - return getCiphertextBlocksize() * 2; - } + public readonly int NBitCount; + public readonly int NLength; + public readonly BigInteger NSquare; + public readonly int NSquareLength; - public int getNLength() - { - return (_n.BitCount() + 7) / 8; - } - - public int getNSquareLength() - { - return getNLength() * 2; - } + public readonly int CiphertextBlocksize; + public readonly int CiphertextLength; } } diff --git a/test/PaillierTests/EdgeCases.cs b/test/PaillierTests/EdgeCases.cs index df8c14e..0631eb7 100644 --- a/test/PaillierTests/EdgeCases.cs +++ b/test/PaillierTests/EdgeCases.cs @@ -30,16 +30,10 @@ public void TestZero() { for (var keySize = 384; keySize <= 1088; keySize += 8) { - var algorithm = new Paillier - { - KeySize = keySize - }; + var algorithm = new Paillier(keySize); - var encryptAlgorithm = new Paillier(); - encryptAlgorithm.FromXmlString(algorithm.ToXmlString(false)); - - var decryptAlgorithm = new Paillier(); - decryptAlgorithm.FromXmlString(algorithm.ToXmlString(true)); + var encryptAlgorithm = new Paillier(algorithm.ToXmlString(false)); + var decryptAlgorithm = new Paillier(algorithm.ToXmlString(true)); var z = new BigInteger(0); var r = new BigInteger(rnd.Next(1, 65536)); @@ -80,17 +74,10 @@ public void MinAndMaxValues() for (var keySize = 384; keySize <= 1088; keySize += 8) { - var algorithm = new Paillier - { - KeySize = keySize - }; - - var encryptAlgorithm = new Paillier(); - encryptAlgorithm.FromXmlString(algorithm.ToXmlString(false)); - - var decryptAlgorithm = new Paillier(); - decryptAlgorithm.FromXmlString(algorithm.ToXmlString(true)); + var algorithm = new Paillier(keySize); + var encryptAlgorithm = new Paillier(algorithm.ToXmlString(false)); + var decryptAlgorithm = new Paillier(algorithm.ToXmlString(true)); // MAX var max_enc = encryptAlgorithm.EncryptData(max); @@ -127,19 +114,13 @@ public void BigDenominator() { for (var keySize = 384; keySize <= 1088; keySize += 8) { - var algorithm = new Paillier - { - KeySize = keySize - }; - - var encryptAlgorithm = new Paillier(); - encryptAlgorithm.FromXmlString(algorithm.ToXmlString(false)); + var algorithm = new Paillier(keySize); - var decryptAlgorithm = new Paillier(); - decryptAlgorithm.FromXmlString(algorithm.ToXmlString(true)); + var encryptAlgorithm = new Paillier(algorithm.ToXmlString(false)); + var decryptAlgorithm = new Paillier(algorithm.ToXmlString(true)); var n = new BigInteger(10000); - var d = algorithm.KeyStruct.PlaintextExp * 2; + var d = algorithm.PlaintextExp * 2; var f = new BigFraction(n, d); var f_enc = encryptAlgorithm.EncryptData(f); diff --git a/test/PaillierTests/FpAddSub.cs b/test/PaillierTests/FpAddSub.cs index a7bfce2..2756c15 100644 --- a/test/PaillierTests/FpAddSub.cs +++ b/test/PaillierTests/FpAddSub.cs @@ -35,29 +35,22 @@ public void TestMultiplication_BatchFrac() { for (var keySize = 384; keySize <= 1088; keySize += 8) { - var algorithm = new Paillier - { - KeySize = keySize - }; - - var encryptAlgorithm = new Paillier(); - encryptAlgorithm.FromXmlString(algorithm.ToXmlString(false)); - - var decryptAlgorithm = new Paillier(); - decryptAlgorithm.FromXmlString(algorithm.ToXmlString(true)); + var algorithm = new Paillier(keySize); + var encryptAlgorithm = new Paillier(algorithm.ToXmlString(false)); + var decryptAlgorithm = new Paillier(algorithm.ToXmlString(true)); BigFraction a, b; do { - var n = new BigInteger().GenRandomBits(rnd.Next(1, algorithm.KeyStruct.getMaxPlaintextBits() / 4), rng); - var d = new BigInteger(Math.Pow(10, (rnd.Next() % algorithm.KeyStruct.getPlaintextDecPlace()) + 1)); + var n = new BigInteger().GenRandomBits(rnd.Next(1, algorithm.MaxPlaintextBits() / 4), rng); + var d = new BigInteger(Math.Pow(10, (rnd.Next() % algorithm.GetPlaintextDecPlace()) + 1)); a = new BigFraction(n, d); } while (a == 0); do { - var n = new BigInteger().GenRandomBits(rnd.Next(1, algorithm.KeyStruct.getMaxPlaintextBits() / 4), rng); - var d = new BigInteger(Math.Pow(10, (rnd.Next() % algorithm.KeyStruct.getPlaintextDecPlace()) + 1)); + var n = new BigInteger().GenRandomBits(rnd.Next(1, algorithm.MaxPlaintextBits() / 4), rng); + var d = new BigInteger(Math.Pow(10, (rnd.Next() % algorithm.GetPlaintextDecPlace()) + 1)); b = new BigFraction(n, d); } while (b == 0); diff --git a/test/PaillierTests/FpEncDec.cs b/test/PaillierTests/FpEncDec.cs index 605aaaa..6811472 100644 --- a/test/PaillierTests/FpEncDec.cs +++ b/test/PaillierTests/FpEncDec.cs @@ -32,19 +32,14 @@ public void TestRandomBigFraction() { for (var keySize = 384; keySize <= 1088; keySize += 8) { - var algorithm = new Paillier - { - KeySize = keySize - }; + var algorithm = new Paillier(keySize); - var encryptAlgorithm = new Paillier(); - encryptAlgorithm.FromXmlString(algorithm.ToXmlString(false)); + var encryptAlgorithm = new Paillier(algorithm.ToXmlString(false)); - var decryptAlgorithm = new Paillier(); - decryptAlgorithm.FromXmlString(algorithm.ToXmlString(true)); + var decryptAlgorithm = new Paillier(algorithm.ToXmlString(true)); - var n = new BigInteger().GenRandomBits(rnd.Next(1, algorithm.KeyStruct.getMaxPlaintextBits() - 1), rng); - var d = new BigInteger(Math.Pow(10, (rnd.Next() % algorithm.KeyStruct.getPlaintextDecPlace()) + 1)); + var n = new BigInteger().GenRandomBits(rnd.Next(1, algorithm.MaxPlaintextBits() - 1), rng); + var d = new BigInteger(Math.Pow(10, (rnd.Next() % algorithm.GetPlaintextDecPlace()) + 1)); var f = new BigFraction(n, d); if (rnd.Next() % 2 == 0) // random sign f *= -1; diff --git a/test/PaillierTests/IntAddSub.cs b/test/PaillierTests/IntAddSub.cs index 49ac530..9c02adb 100644 --- a/test/PaillierTests/IntAddSub.cs +++ b/test/PaillierTests/IntAddSub.cs @@ -35,25 +35,19 @@ public void TestMultiplication_Batch() { for (var keySize = 384; keySize <= 1088; keySize += 8) { - var algorithm = new Paillier - { - KeySize = keySize - }; - - var encryptAlgorithm = new Paillier(); - encryptAlgorithm.FromXmlString(algorithm.ToXmlString(false)); + var algorithm = new Paillier(keySize); - var decryptAlgorithm = new Paillier(); - decryptAlgorithm.FromXmlString(algorithm.ToXmlString(true)); + var encryptAlgorithm = new Paillier(algorithm.ToXmlString(false)); + var decryptAlgorithm = new Paillier(algorithm.ToXmlString(true)); BigInteger a, b; do { - a = new BigInteger().GenRandomBits(rnd.Next(1, algorithm.KeyStruct.getMaxPlaintextBits() / 4), rng); + a = new BigInteger().GenRandomBits(rnd.Next(1, algorithm.MaxPlaintextBits() / 4), rng); } while (a == 0); do { - b = new BigInteger().GenRandomBits(rnd.Next(1, algorithm.KeyStruct.getMaxPlaintextBits() / 4), rng); + b = new BigInteger().GenRandomBits(rnd.Next(1, algorithm.MaxPlaintextBits() / 4), rng); } while (b == 0); if (rnd.Next() % 2 == 0) // randomly change signs diff --git a/test/PaillierTests/IntEncDec.cs b/test/PaillierTests/IntEncDec.cs index 4c3a8ce..8e04cea 100644 --- a/test/PaillierTests/IntEncDec.cs +++ b/test/PaillierTests/IntEncDec.cs @@ -32,20 +32,15 @@ public void TestRandomBigInteger() { for (var keySize = 384; keySize <= 1088; keySize += 8) { - var algorithm = new Paillier - { - KeySize = keySize - }; + var algorithm = new Paillier(keySize); - var encryptAlgorithm = new Paillier(); - encryptAlgorithm.FromXmlString(algorithm.ToXmlString(false)); + var encryptAlgorithm = new Paillier(algorithm.ToXmlString(false)); - var decryptAlgorithm = new Paillier(); - decryptAlgorithm.FromXmlString(algorithm.ToXmlString(true)); + var decryptAlgorithm = new Paillier(algorithm.ToXmlString(true)); var z = new BigInteger(); - z = z.GenRandomBits(rnd.Next(1, algorithm.KeyStruct.getMaxPlaintextBits() - 1), rng); + z = z.GenRandomBits(rnd.Next(1, algorithm.MaxPlaintextBits() - 1), rng); if (rnd.Next() % 2 == 0) // random sign z = -z; diff --git a/test/PaillierTests/KeyStruct.cs b/test/PaillierTests/KeyStruct.cs index a8e043d..00a53c9 100644 --- a/test/PaillierTests/KeyStruct.cs +++ b/test/PaillierTests/KeyStruct.cs @@ -1,5 +1,7 @@ using System; +using System.Numerics; using System.Security.Cryptography; +using Aprismatic; using Aprismatic.PaillierExt; using Xunit; using Xunit.Abstractions; @@ -26,19 +28,15 @@ public void Dispose() [Fact(DisplayName = "Lengths")] public void TestLengths() { - var rnd = new Random(); - var rng = new RNGCryptoServiceProvider(); - for (var i = 0; i < Globals.iterations; i++) { for (var keySize = 384; keySize <= 1088; keySize += 8) { - var algorithm = new Paillier - { - KeySize = keySize - }; + var algorithm = new Paillier(keySize); + var prms = algorithm.ExportParameters(false); + var bi = new BigInteger(prms.N); - Assert.Equal(algorithm.KeySize / 8, algorithm.KeyStruct.getNLength()); + Assert.Equal(algorithm.KeySize / 8, (bi.BitCount() + 7) / 8); algorithm.Dispose(); } diff --git a/test/PaillierTests/PaillierTests.csproj b/test/PaillierTests/PaillierTests.csproj index 273566c..57f339d 100644 --- a/test/PaillierTests/PaillierTests.csproj +++ b/test/PaillierTests/PaillierTests.csproj @@ -4,7 +4,7 @@ false - + all diff --git a/test/PaillierTests/SimpleFastTests.cs b/test/PaillierTests/SimpleFastTests.cs index 94a345d..ff0ad78 100644 --- a/test/PaillierTests/SimpleFastTests.cs +++ b/test/PaillierTests/SimpleFastTests.cs @@ -29,10 +29,7 @@ public void Dispose() public void TestSpecificCases() { { - var algorithm = new Paillier - { - KeySize = 384 - }; + var algorithm = new Paillier(384); var z = new BigFraction(BigInteger.Parse("1000"), BigInteger.Parse("1")); @@ -48,10 +45,7 @@ public void TestSpecificCases() // based on https://github.com/bazzilic/PaillierExt/issues/15 for (var keySize = 384; keySize <= 1088; keySize += 8) { - var algorithm = new Paillier - { - KeySize = keySize - }; + var algorithm = new Paillier(keySize); var sum = algorithm.EncryptData(new BigInteger(0)); var one = algorithm.EncryptData(new BigInteger(1)); @@ -72,10 +66,7 @@ public void TestSpecificCases() { for (var keySize = 384; keySize <= 1088; keySize += 8) { - var algorithm = new Paillier - { - KeySize = keySize - }; + var algorithm = new Paillier(keySize); var a = 123; var b = 234; @@ -117,10 +108,7 @@ public void TestSpecificCases() public void TestNegativeCases() { { - var algorithm = new Paillier - { - KeySize = 384 - }; + var algorithm = new Paillier(384); //Test negative number var z = new BigInteger(8); @@ -152,10 +140,7 @@ public void TestNegativeCases() public void TestFloatingPoint() { { - var algorithm = new Paillier - { - KeySize = 384 - }; + var algorithm = new Paillier(384); //Test 1 decimal place var z = new BigFraction(BigInteger.Parse("1"), BigInteger.Parse("10")); @@ -188,10 +173,7 @@ public void TestFloatingPoint() public void TestNegativeFloatingPoint() { { - var algorithm = new Paillier - { - KeySize = 384 - }; + var algorithm = new Paillier(384); //Test 0 > plaintext > -1 var z = new BigFraction(BigInteger.Parse("-1001"), BigInteger.Parse("100"));