<PackageReference Include="BouncyCastle.Cryptography" Version="2.3.1" />

NtruOwcpa

class NtruOwcpa
An OW-CPA secure deterministic public key encryption scheme (DPKE).
using Org.BouncyCastle.Pqc.Crypto.Ntru.ParameterSets; using Org.BouncyCastle.Pqc.Crypto.Ntru.Polynomials; using Org.BouncyCastle.Utilities; using System; namespace Org.BouncyCastle.Pqc.Crypto.Ntru.Owcpa { internal class NtruOwcpa { private readonly NtruParameterSet _parameterSet; private readonly NtruSampling _sampling; internal NtruOwcpa(NtruParameterSet parameterSet) { _parameterSet = parameterSet; _sampling = new NtruSampling(parameterSet); } internal OwcpaKeyPair KeyPair(byte[] seed) { byte[] array = new byte[_parameterSet.OwcpaSecretKeyBytes()]; int n = _parameterSet.N; _parameterSet.Q(); _parameterSet.CreatePolynomial(); _parameterSet.CreatePolynomial(); Polynomial polynomial = _parameterSet.CreatePolynomial(); Polynomial polynomial2 = _parameterSet.CreatePolynomial(); Polynomial polynomial3 = _parameterSet.CreatePolynomial(); Polynomial polynomial4 = polynomial; Polynomial polynomial5 = polynomial; Polynomial polynomial6 = polynomial2; Polynomial polynomial7 = polynomial3; Polynomial polynomial8 = polynomial; Polynomial polynomial9 = polynomial; PolynomialPair polynomialPair = _sampling.SampleFg(seed); Polynomial polynomial10 = polynomialPair.F(); Polynomial polynomial11 = polynomialPair.G(); polynomial4.S3Inv(polynomial10); byte[] array2 = polynomial10.S3ToBytes(_parameterSet.OwcpaMsgBytes()); Array.Copy(array2, 0, array, 0, array2.Length); byte[] array3 = polynomial4.S3ToBytes(array.Length - _parameterSet.PackTrinaryBytes()); Array.Copy(array3, 0, array, _parameterSet.PackTrinaryBytes(), array3.Length); polynomial10.Z3ToZq(); polynomial11.Z3ToZq(); if (_parameterSet is NtruHrssParameterSet) { for (int num = n - 1; num > 0; num--) { polynomial11.coeffs[num] = (ushort)(3 * (polynomial11.coeffs[num - 1] - polynomial11.coeffs[num])); } polynomial11.coeffs[0] = (ushort)(-(3 * polynomial11.coeffs[0])); } else { for (int num = 0; num < n; num++) { polynomial11.coeffs[num] = (ushort)(3 * polynomial11.coeffs[num]); } } polynomial5.RqMul(polynomial11, polynomial10); polynomial6.RqInv(polynomial5); polynomial7.RqMul(polynomial6, polynomial10); polynomial8.SqMul(polynomial7, polynomial10); byte[] array4 = polynomial8.SqToBytes(array.Length - 2 * _parameterSet.PackTrinaryBytes()); Array.Copy(array4, 0, array, 2 * _parameterSet.PackTrinaryBytes(), array4.Length); polynomial7.RqMul(polynomial6, polynomial11); polynomial9.RqMul(polynomial7, polynomial11); return new OwcpaKeyPair(polynomial9.RqSumZeroToBytes(_parameterSet.OwcpaPublicKeyBytes()), array); } internal byte[] Encrypt(Polynomial r, Polynomial m, byte[] publicKey) { Polynomial polynomial = _parameterSet.CreatePolynomial(); Polynomial polynomial2 = _parameterSet.CreatePolynomial(); Polynomial polynomial3 = polynomial; Polynomial polynomial4 = polynomial; Polynomial polynomial5 = polynomial2; polynomial3.RqSumZeroFromBytes(publicKey); polynomial5.RqMul(r, polynomial3); polynomial4.Lift(m); for (int i = 0; i < _parameterSet.N; i++) { polynomial5.coeffs[i] += polynomial4.coeffs[i]; } return polynomial5.RqSumZeroToBytes(_parameterSet.NtruCiphertextBytes()); } internal OwcpaDecryptResult Decrypt(byte[] ciphertext, byte[] privateKey) { byte[] array = new byte[_parameterSet.OwcpaMsgBytes()]; Polynomial polynomial = _parameterSet.CreatePolynomial(); Polynomial polynomial2 = _parameterSet.CreatePolynomial(); Polynomial polynomial3 = _parameterSet.CreatePolynomial(); Polynomial polynomial4 = _parameterSet.CreatePolynomial(); Polynomial polynomial5 = polynomial; Polynomial polynomial6 = polynomial2; Polynomial polynomial7 = polynomial3; Polynomial polynomial8 = polynomial2; Polynomial polynomial9 = polynomial3; Polynomial polynomial10 = polynomial4; Polynomial polynomial11 = polynomial2; Polynomial polynomial12 = polynomial3; Polynomial polynomial13 = polynomial4; Polynomial polynomial14 = polynomial; polynomial5.RqSumZeroFromBytes(ciphertext); polynomial6.S3FromBytes(privateKey); polynomial6.Z3ToZq(); polynomial7.RqMul(polynomial5, polynomial6); polynomial8.RqToS3(polynomial7); polynomial9.S3FromBytes(Arrays.CopyOfRange(privateKey, _parameterSet.PackTrinaryBytes(), privateKey.Length)); polynomial10.S3Mul(polynomial8, polynomial9); byte[] array2 = polynomial10.S3ToBytes(array.Length - _parameterSet.PackTrinaryBytes()); int num = 0; num |= CheckCiphertext(ciphertext); if (_parameterSet is NtruHpsParameterSet) num |= CheckM((HpsPolynomial)polynomial10); polynomial11.Lift(polynomial10); for (int i = 0; i < _parameterSet.N; i++) { polynomial14.coeffs[i] = (ushort)(polynomial5.coeffs[i] - polynomial11.coeffs[i]); } polynomial12.SqFromBytes(Arrays.CopyOfRange(privateKey, 2 * _parameterSet.PackTrinaryBytes(), privateKey.Length)); polynomial13.SqMul(polynomial14, polynomial12); num |= CheckR(polynomial13); polynomial13.TrinaryZqToZ3(); byte[] array3 = polynomial13.S3ToBytes(_parameterSet.OwcpaMsgBytes()); Array.Copy(array3, 0, array, 0, array3.Length); Array.Copy(array2, 0, array, _parameterSet.PackTrinaryBytes(), array2.Length); return new OwcpaDecryptResult(array, num); } private int CheckCiphertext(byte[] ciphertext) { ushort num = ciphertext[_parameterSet.NtruCiphertextBytes() - 1]; num = (ushort)(num & (ushort)(255 << 8 - (7 & (_parameterSet.LogQ * _parameterSet.PackDegree())))); return 1 & (~num + 1 >> 15); } private int CheckR(Polynomial r) { int num = 0; for (int i = 0; i < _parameterSet.N - 1; i++) { ushort num2 = r.coeffs[i]; num |= ((num2 + 1) & (_parameterSet.Q() - 4)); num |= ((num2 + 2) & 4); } num |= r.coeffs[_parameterSet.N - 1]; return 1 & (~num + 1 >> 31); } private int CheckM(HpsPolynomial m) { int num = 0; ushort num2 = 0; ushort num3 = 0; for (int i = 0; i < _parameterSet.N - 1; i++) { num2 = (ushort)(num2 + (ushort)(m.coeffs[i] & 1)); num3 = (ushort)(num3 + (ushort)(m.coeffs[i] & 2)); } num |= (num2 ^ (num3 >> 1)); num |= (num3 ^ ((NtruHpsParameterSet)_parameterSet).Weight()); return 1 & (~num + 1 >> 31); } } }