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);
}
}
}