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

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; Polynomial polynomial = _parameterSet.CreatePolynomial(); Polynomial polynomial2 = _parameterSet.CreatePolynomial(); Polynomial polynomial3 = _parameterSet.CreatePolynomial(); PolynomialPair polynomialPair = _sampling.SampleFg(seed); Polynomial polynomial4 = polynomialPair.F(); Polynomial polynomial5 = polynomialPair.G(); polynomial.S3Inv(polynomial4); polynomial4.S3ToBytes(array, 0); polynomial.S3ToBytes(array, _parameterSet.PackTrinaryBytes()); polynomial4.Z3ToZq(); polynomial5.Z3ToZq(); if (_parameterSet is NtruHrssParameterSet) { for (int num = n - 1; num > 0; num--) { polynomial5.coeffs[num] = (ushort)(3 * (polynomial5.coeffs[num - 1] - polynomial5.coeffs[num])); } polynomial5.coeffs[0] = (ushort)(-(3 * polynomial5.coeffs[0])); } else { for (int num = 0; num < n; num++) { polynomial5.coeffs[num] = (ushort)(3 * polynomial5.coeffs[num]); } } polynomial.RqMul(polynomial5, polynomial4); polynomial2.RqInv(polynomial); polynomial3.RqMul(polynomial2, polynomial4); polynomial.SqMul(polynomial3, polynomial4); byte[] array2 = polynomial.SqToBytes(array.Length - 2 * _parameterSet.PackTrinaryBytes()); Array.Copy(array2, 0, array, 2 * _parameterSet.PackTrinaryBytes(), array2.Length); polynomial3.RqMul(polynomial2, polynomial5); polynomial.RqMul(polynomial3, polynomial5); return new OwcpaKeyPair(polynomial.RqSumZeroToBytes(_parameterSet.OwcpaPublicKeyBytes()), array); } internal byte[] Encrypt(Polynomial r, Polynomial m, byte[] publicKey) { Polynomial polynomial = _parameterSet.CreatePolynomial(); Polynomial polynomial2 = _parameterSet.CreatePolynomial(); polynomial.RqSumZeroFromBytes(publicKey); polynomial2.RqMul(r, polynomial); polynomial.Lift(m); for (int i = 0; i < _parameterSet.N; i++) { polynomial2.coeffs[i] += polynomial.coeffs[i]; } return polynomial2.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.RqSumZeroFromBytes(ciphertext); polynomial2.S3FromBytes(privateKey); polynomial2.Z3ToZq(); polynomial3.RqMul(polynomial, polynomial2); polynomial2.RqToS3(polynomial3); polynomial3.S3FromBytes(Arrays.CopyOfRange(privateKey, _parameterSet.PackTrinaryBytes(), privateKey.Length)); polynomial4.S3Mul(polynomial2, polynomial3); polynomial4.S3ToBytes(array, _parameterSet.PackTrinaryBytes()); int num = 0; num |= CheckCiphertext(ciphertext); if (_parameterSet is NtruHpsParameterSet) num |= CheckM((HpsPolynomial)polynomial4); polynomial2.Lift(polynomial4); for (int i = 0; i < _parameterSet.N; i++) { polynomial.coeffs[i] = (ushort)(polynomial.coeffs[i] - polynomial2.coeffs[i]); } polynomial3.SqFromBytes(Arrays.CopyOfRange(privateKey, 2 * _parameterSet.PackTrinaryBytes(), privateKey.Length)); polynomial4.SqMul(polynomial, polynomial3); num |= CheckR(polynomial4); polynomial4.TrinaryZqToZ3(); polynomial4.S3ToBytes(array, 0); 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); } } }