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