PqcOtherInfoGenerator
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Utilities;
using Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber;
using Org.BouncyCastle.Pqc.Crypto.Ntru;
using Org.BouncyCastle.Security;
using System;
using System.IO;
namespace Org.BouncyCastle.Pqc.Crypto.Utilities
{
public abstract class PqcOtherInfoGenerator
{
public sealed class PartyU : PqcOtherInfoGenerator
{
private AsymmetricCipherKeyPair m_aKp;
private IEncapsulatedSecretExtractor m_encSE;
public PartyU(IKemParameters kemParams, AlgorithmIdentifier algorithmID, byte[] partyUInfo, byte[] partyVInfo, SecureRandom random)
: base(algorithmID, partyUInfo, partyVInfo, random)
{
KyberParameters kyberParameters = kemParams as KyberParameters;
if (kyberParameters != null) {
KyberKeyPairGenerator kyberKeyPairGenerator = new KyberKeyPairGenerator();
kyberKeyPairGenerator.Init(new KyberKeyGenerationParameters(random, kyberParameters));
m_aKp = kyberKeyPairGenerator.GenerateKeyPair();
m_encSE = new KyberKemExtractor((KyberPrivateKeyParameters)m_aKp.Private);
} else {
NtruParameters ntruParameters = kemParams as NtruParameters;
if (ntruParameters == null)
throw new ArgumentException("unknown IKemParameters");
NtruKeyPairGenerator ntruKeyPairGenerator = new NtruKeyPairGenerator();
ntruKeyPairGenerator.Init(new NtruKeyGenerationParameters(random, ntruParameters));
m_aKp = ntruKeyPairGenerator.GenerateKeyPair();
m_encSE = new NtruKemExtractor((NtruPrivateKeyParameters)m_aKp.Private);
}
}
public PqcOtherInfoGenerator WithSuppPubInfo(byte[] suppPubInfo)
{
m_otherInfoBuilder.WithSuppPubInfo(suppPubInfo);
return this;
}
public byte[] GetSuppPrivInfoPartA()
{
return GetEncoded(m_aKp.Public);
}
public DerOtherInfo Generate(byte[] suppPrivInfoPartB)
{
m_otherInfoBuilder.WithSuppPrivInfo(m_encSE.ExtractSecret(suppPrivInfoPartB));
return m_otherInfoBuilder.Build();
}
}
public sealed class PartyV : PqcOtherInfoGenerator
{
private IEncapsulatedSecretGenerator m_encSG;
public PartyV(IKemParameters kemParams, AlgorithmIdentifier algorithmID, byte[] partyUInfo, byte[] partyVInfo, SecureRandom random)
: base(algorithmID, partyUInfo, partyVInfo, random)
{
if (kemParams is KyberParameters)
m_encSG = new KyberKemGenerator(random);
else {
if (!(kemParams is NtruParameters))
throw new ArgumentException("unknown IKemParameters");
m_encSG = new NtruKemGenerator(random);
}
}
public PqcOtherInfoGenerator WithSuppPubInfo(byte[] suppPubInfo)
{
m_otherInfoBuilder.WithSuppPubInfo(suppPubInfo);
return this;
}
public byte[] GetSuppPrivInfoPartB(byte[] suppPrivInfoPartA)
{
m_used = false;
try {
ISecretWithEncapsulation secretWithEncapsulation = m_encSG.GenerateEncapsulated(GetPublicKey(suppPrivInfoPartA));
m_otherInfoBuilder.WithSuppPrivInfo(secretWithEncapsulation.GetSecret());
return secretWithEncapsulation.GetEncapsulation();
} catch (IOException innerException) {
throw new ArgumentException("cannot decode public key", innerException);
}
}
public DerOtherInfo Generate()
{
if (m_used)
throw new InvalidOperationException("builder already used");
m_used = true;
return m_otherInfoBuilder.Build();
}
}
protected readonly DerOtherInfo.Builder m_otherInfoBuilder;
protected readonly SecureRandom m_random;
protected bool m_used;
internal PqcOtherInfoGenerator(AlgorithmIdentifier algorithmID, byte[] partyUInfo, byte[] partyVInfo, SecureRandom random)
{
m_otherInfoBuilder = new DerOtherInfo.Builder(algorithmID, partyUInfo, partyVInfo);
m_random = random;
}
private static byte[] GetEncoded(AsymmetricKeyParameter pubKey)
{
try {
return PqcSubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubKey).GetEncoded();
} catch (IOException) {
return null;
}
}
private static AsymmetricKeyParameter GetPublicKey(byte[] enc)
{
return PqcPublicKeyFactory.CreateKey(enc);
}
}
}