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

NtruKemExtractor

NTRU secret encapsulation extractor.
using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Pqc.Crypto.Ntru.Owcpa; using Org.BouncyCastle.Pqc.Crypto.Ntru.ParameterSets; using Org.BouncyCastle.Utilities; using System; namespace Org.BouncyCastle.Pqc.Crypto.Ntru { public class NtruKemExtractor : IEncapsulatedSecretExtractor { private readonly NtruPrivateKeyParameters m_privateKey; public int EncapsulationLength => m_privateKey.Parameters.ParameterSet.NtruCiphertextBytes(); public NtruKemExtractor(NtruPrivateKeyParameters ntruPrivateKey) { if (ntruPrivateKey == null) throw new ArgumentNullException("ntruPrivateKey"); m_privateKey = ntruPrivateKey; } public byte[] ExtractSecret(byte[] encapsulation) { NtruParameterSet parameterSet = m_privateKey.Parameters.ParameterSet; if (encapsulation == null) throw new ArgumentNullException("encapsulation"); if (encapsulation.Length != parameterSet.NtruCiphertextBytes()) throw new ArgumentException("encapsulation"); byte[] encoded = m_privateKey.GetEncoded(); OwcpaDecryptResult owcpaDecryptResult = new NtruOwcpa(parameterSet).Decrypt(encapsulation, encoded); byte[] rm = owcpaDecryptResult.Rm; int fail = owcpaDecryptResult.Fail; Sha3Digest sha3Digest = new Sha3Digest(256); byte[] array = new byte[sha3Digest.GetDigestSize()]; sha3Digest.BlockUpdate(rm, 0, rm.Length); sha3Digest.DoFinal(array, 0); sha3Digest.BlockUpdate(encoded, parameterSet.OwcpaSecretKeyBytes(), parameterSet.PrfKeyBytes); sha3Digest.BlockUpdate(encapsulation, 0, encapsulation.Length); sha3Digest.DoFinal(rm, 0); Cmov(array, rm, (byte)fail); byte[] result = Arrays.CopyOfRange(array, 0, parameterSet.SharedKeyBytes); Array.Clear(array, 0, array.Length); return result; } private static void Cmov(byte[] r, byte[] x, byte b) { b = (byte)(~b + 1); for (int i = 0; i < r.Length; i++) { r[i] ^= (byte)(b & (x[i] ^ r[i])); } } } }