PqcPublicKeyFactory
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.BC;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Utilities;
using Org.BouncyCastle.Pqc.Asn1;
using Org.BouncyCastle.Pqc.Crypto.Bike;
using Org.BouncyCastle.Pqc.Crypto.Cmce;
using Org.BouncyCastle.Pqc.Crypto.Crystals.Dilithium;
using Org.BouncyCastle.Pqc.Crypto.Falcon;
using Org.BouncyCastle.Pqc.Crypto.Frodo;
using Org.BouncyCastle.Pqc.Crypto.Hqc;
using Org.BouncyCastle.Pqc.Crypto.Lms;
using Org.BouncyCastle.Pqc.Crypto.Ntru;
using Org.BouncyCastle.Pqc.Crypto.Picnic;
using Org.BouncyCastle.Pqc.Crypto.Saber;
using Org.BouncyCastle.Pqc.Crypto.SphincsPlus;
using Org.BouncyCastle.Utilities;
using System;
using System.Collections.Generic;
using System.IO;
namespace Org.BouncyCastle.Pqc.Crypto.Utilities
{
public static class PqcPublicKeyFactory
{
private delegate AsymmetricKeyParameter Converter (SubjectPublicKeyInfo keyInfo, object defaultParams);
private static Dictionary<DerObjectIdentifier, Converter> Converters;
static PqcPublicKeyFactory()
{
Converters = new Dictionary<DerObjectIdentifier, Converter>();
Converters[PkcsObjectIdentifiers.IdAlgHssLmsHashsig] = LmsConverter;
Converters[BCObjectIdentifiers.mceliece348864_r3] = CmceConverter;
Converters[BCObjectIdentifiers.mceliece348864f_r3] = CmceConverter;
Converters[BCObjectIdentifiers.mceliece460896_r3] = CmceConverter;
Converters[BCObjectIdentifiers.mceliece460896f_r3] = CmceConverter;
Converters[BCObjectIdentifiers.mceliece6688128_r3] = CmceConverter;
Converters[BCObjectIdentifiers.mceliece6688128f_r3] = CmceConverter;
Converters[BCObjectIdentifiers.mceliece6960119_r3] = CmceConverter;
Converters[BCObjectIdentifiers.mceliece6960119f_r3] = CmceConverter;
Converters[BCObjectIdentifiers.mceliece8192128_r3] = CmceConverter;
Converters[BCObjectIdentifiers.mceliece8192128f_r3] = CmceConverter;
Converters[BCObjectIdentifiers.frodokem640aes] = FrodoConverter;
Converters[BCObjectIdentifiers.frodokem640shake] = FrodoConverter;
Converters[BCObjectIdentifiers.frodokem976aes] = FrodoConverter;
Converters[BCObjectIdentifiers.frodokem976shake] = FrodoConverter;
Converters[BCObjectIdentifiers.frodokem1344aes] = FrodoConverter;
Converters[BCObjectIdentifiers.frodokem1344shake] = FrodoConverter;
Converters[BCObjectIdentifiers.lightsaberkem128r3] = SaberConverter;
Converters[BCObjectIdentifiers.saberkem128r3] = SaberConverter;
Converters[BCObjectIdentifiers.firesaberkem128r3] = SaberConverter;
Converters[BCObjectIdentifiers.lightsaberkem192r3] = SaberConverter;
Converters[BCObjectIdentifiers.saberkem192r3] = SaberConverter;
Converters[BCObjectIdentifiers.firesaberkem192r3] = SaberConverter;
Converters[BCObjectIdentifiers.lightsaberkem256r3] = SaberConverter;
Converters[BCObjectIdentifiers.saberkem256r3] = SaberConverter;
Converters[BCObjectIdentifiers.firesaberkem256r3] = SaberConverter;
Converters[BCObjectIdentifiers.ulightsaberkemr3] = SaberConverter;
Converters[BCObjectIdentifiers.usaberkemr3] = SaberConverter;
Converters[BCObjectIdentifiers.ufiresaberkemr3] = SaberConverter;
Converters[BCObjectIdentifiers.lightsaberkem90sr3] = SaberConverter;
Converters[BCObjectIdentifiers.saberkem90sr3] = SaberConverter;
Converters[BCObjectIdentifiers.firesaberkem90sr3] = SaberConverter;
Converters[BCObjectIdentifiers.ulightsaberkem90sr3] = SaberConverter;
Converters[BCObjectIdentifiers.usaberkem90sr3] = SaberConverter;
Converters[BCObjectIdentifiers.ufiresaberkem90sr3] = SaberConverter;
Converters[BCObjectIdentifiers.picnic] = PicnicConverter;
Converters[BCObjectIdentifiers.picnicl1fs] = PicnicConverter;
Converters[BCObjectIdentifiers.picnicl1ur] = PicnicConverter;
Converters[BCObjectIdentifiers.picnicl3fs] = PicnicConverter;
Converters[BCObjectIdentifiers.picnicl3ur] = PicnicConverter;
Converters[BCObjectIdentifiers.picnicl5fs] = PicnicConverter;
Converters[BCObjectIdentifiers.picnicl5ur] = PicnicConverter;
Converters[BCObjectIdentifiers.picnic3l1] = PicnicConverter;
Converters[BCObjectIdentifiers.picnic3l3] = PicnicConverter;
Converters[BCObjectIdentifiers.picnic3l5] = PicnicConverter;
Converters[BCObjectIdentifiers.picnicl1full] = PicnicConverter;
Converters[BCObjectIdentifiers.picnicl3full] = PicnicConverter;
Converters[BCObjectIdentifiers.picnicl5full] = PicnicConverter;
Converters.Add(BCObjectIdentifiers.ntruhps2048509, NtruConverter);
Converters.Add(BCObjectIdentifiers.ntruhps2048677, NtruConverter);
Converters.Add(BCObjectIdentifiers.ntruhps4096821, NtruConverter);
Converters.Add(BCObjectIdentifiers.ntruhps40961229, NtruConverter);
Converters.Add(BCObjectIdentifiers.ntruhrss701, NtruConverter);
Converters.Add(BCObjectIdentifiers.ntruhrss1373, NtruConverter);
Converters[BCObjectIdentifiers.dilithium2] = DilithiumConverter;
Converters[BCObjectIdentifiers.dilithium3] = DilithiumConverter;
Converters[BCObjectIdentifiers.dilithium5] = DilithiumConverter;
Converters[BCObjectIdentifiers.dilithium2_aes] = DilithiumConverter;
Converters[BCObjectIdentifiers.dilithium3_aes] = DilithiumConverter;
Converters[BCObjectIdentifiers.dilithium5_aes] = DilithiumConverter;
Converters[BCObjectIdentifiers.falcon_512] = FalconConverter;
Converters[BCObjectIdentifiers.falcon_1024] = FalconConverter;
Converters[BCObjectIdentifiers.bike128] = BikeConverter;
Converters[BCObjectIdentifiers.bike192] = BikeConverter;
Converters[BCObjectIdentifiers.bike256] = BikeConverter;
Converters[BCObjectIdentifiers.hqc128] = HqcConverter;
Converters[BCObjectIdentifiers.hqc192] = HqcConverter;
Converters[BCObjectIdentifiers.hqc256] = HqcConverter;
Converters[BCObjectIdentifiers.sphincsPlus] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_sha2_128s_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_sha2_128f_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_shake_128s_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_shake_128f_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_haraka_128s_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_haraka_128f_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_sha2_192s_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_sha2_192f_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_shake_192s_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_shake_192f_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_haraka_192s_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_haraka_192f_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_sha2_256s_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_sha2_256f_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_shake_256s_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_shake_256f_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_haraka_256s_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_haraka_256f_r3] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_haraka_128f_r3_simple] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_haraka_128s_r3_simple] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_haraka_192f_r3_simple] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_haraka_192s_r3_simple] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_haraka_256f_r3_simple] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_haraka_256s_r3_simple] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_sha2_128s] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_sha2_128f] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_shake_128s] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_shake_128f] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_sha2_192s] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_sha2_192f] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_shake_192s] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_shake_192f] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_sha2_256s] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_sha2_256f] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_shake_256s] = SphincsPlusConverter;
Converters[BCObjectIdentifiers.sphincsPlus_shake_256f] = SphincsPlusConverter;
}
public static AsymmetricKeyParameter CreateKey(byte[] keyInfoData)
{
return CreateKey(SubjectPublicKeyInfo.GetInstance(keyInfoData));
}
public static AsymmetricKeyParameter CreateKey(Stream inStr)
{
return CreateKey(SubjectPublicKeyInfo.GetInstance(Asn1Object.FromStream(inStr)));
}
public static AsymmetricKeyParameter CreateKey(SubjectPublicKeyInfo keyInfo)
{
return CreateKey(keyInfo, null);
}
public static AsymmetricKeyParameter CreateKey(SubjectPublicKeyInfo keyInfo, object defaultParams)
{
DerObjectIdentifier algorithm = keyInfo.Algorithm.Algorithm;
if (!Converters.TryGetValue(algorithm, out Converter value))
throw new IOException("algorithm identifier in public key not recognised: " + algorithm?.ToString());
return value(keyInfo, defaultParams);
}
internal static DilithiumPublicKeyParameters GetDilithiumPublicKey(DilithiumParameters dilithiumParameters, DerBitString publicKeyData)
{
byte[] octets = publicKeyData.GetOctets();
try {
Asn1Object asn1Object = Asn1Object.FromByteArray(octets);
Asn1Sequence asn1Sequence = asn1Object as Asn1Sequence;
if (asn1Sequence == null) {
byte[] octets2 = Asn1OctetString.GetInstance(asn1Object).GetOctets();
return new DilithiumPublicKeyParameters(dilithiumParameters, octets2);
}
return new DilithiumPublicKeyParameters(dilithiumParameters, Asn1OctetString.GetInstance(asn1Sequence[0]).GetOctets(), Asn1OctetString.GetInstance(asn1Sequence[1]).GetOctets());
} catch (Exception) {
return new DilithiumPublicKeyParameters(dilithiumParameters, octets);
}
}
private static AsymmetricKeyParameter LmsConverter(SubjectPublicKeyInfo keyInfo, object defaultParams)
{
DerBitString publicKey = keyInfo.PublicKey;
if (publicKey.IsOctetAligned()) {
try {
Asn1OctetString asn1OctetString = Asn1Object.FromMemoryStream(publicKey.GetOctetMemoryStream()) as Asn1OctetString;
if (asn1OctetString != null)
return GetLmsKeyParameters(asn1OctetString.GetOctets());
} catch (Exception) {
}
return GetLmsKeyParameters(publicKey.GetOctets());
}
throw new ArgumentException("invalid LMS public key");
}
private static LmsKeyParameters GetLmsKeyParameters(byte[] keyEnc)
{
if (keyEnc.Length >= 4 && Pack.BE_To_UInt32(keyEnc, 0) == 1)
return LmsPublicKeyParameters.Parse(keyEnc, 4, keyEnc.Length - 4);
return HssPublicKeyParameters.Parse(keyEnc);
}
private static AsymmetricKeyParameter SphincsPlusConverter(SubjectPublicKeyInfo keyInfo, object defaultParams)
{
try {
byte[] octets = Asn1OctetString.GetInstance(keyInfo.ParsePublicKey()).GetOctets();
return new SphincsPlusPublicKeyParameters(PqcUtilities.SphincsPlusParamsLookup(keyInfo.Algorithm.Algorithm), Arrays.CopyOfRange(octets, 4, octets.Length));
} catch (Exception) {
byte[] octets2 = keyInfo.PublicKey.GetOctets();
return new SphincsPlusPublicKeyParameters(PqcUtilities.SphincsPlusParamsLookup(keyInfo.Algorithm.Algorithm), octets2);
}
}
private static AsymmetricKeyParameter CmceConverter(SubjectPublicKeyInfo keyInfo, object defaultParams)
{
byte[] t = CmcePublicKey.GetInstance(keyInfo.ParsePublicKey()).T;
return new CmcePublicKeyParameters(PqcUtilities.McElieceParamsLookup(keyInfo.Algorithm.Algorithm), t);
}
private static AsymmetricKeyParameter FrodoConverter(SubjectPublicKeyInfo keyInfo, object defaultParams)
{
byte[] octets = Asn1OctetString.GetInstance(keyInfo.ParsePublicKey()).GetOctets();
return new FrodoPublicKeyParameters(PqcUtilities.FrodoParamsLookup(keyInfo.Algorithm.Algorithm), octets);
}
private static AsymmetricKeyParameter SaberConverter(SubjectPublicKeyInfo keyInfo, object defaultParams)
{
byte[] octets = Asn1OctetString.GetInstance(Asn1Sequence.GetInstance(keyInfo.ParsePublicKey())[0]).GetOctets();
return new SaberPublicKeyParameters(PqcUtilities.SaberParamsLookup(keyInfo.Algorithm.Algorithm), octets);
}
private static AsymmetricKeyParameter PicnicConverter(SubjectPublicKeyInfo keyInfo, object defaultParams)
{
byte[] octets = Asn1OctetString.GetInstance(keyInfo.ParsePublicKey()).GetOctets();
return new PicnicPublicKeyParameters(PqcUtilities.PicnicParamsLookup(keyInfo.Algorithm.Algorithm), octets);
}
private static AsymmetricKeyParameter DilithiumConverter(SubjectPublicKeyInfo keyInfo, object defaultParams)
{
return GetDilithiumPublicKey(PqcUtilities.DilithiumParamsLookup(keyInfo.Algorithm.Algorithm), keyInfo.PublicKey);
}
private static AsymmetricKeyParameter NtruConverter(SubjectPublicKeyInfo keyInfo, object defaultParams)
{
return GetNtruPublicKey(PqcUtilities.NtruParamsLookup(keyInfo.Algorithm.Algorithm), keyInfo.PublicKey);
}
private static NtruPublicKeyParameters GetNtruPublicKey(NtruParameters ntruParameters, DerBitString publicKey)
{
if (publicKey.IsOctetAligned()) {
int publicKeyLength = ntruParameters.PublicKeyLength;
int bytesLength = publicKey.GetBytesLength();
if (bytesLength == publicKeyLength)
return NtruPublicKeyParameters.FromEncoding(ntruParameters, publicKey.GetOctets());
if (bytesLength > publicKeyLength)
try {
Asn1OctetString asn1OctetString = Asn1Object.FromMemoryStream(publicKey.GetOctetMemoryStream()) as Asn1OctetString;
if (asn1OctetString != null && asn1OctetString.GetOctetsLength() == publicKeyLength)
return NtruPublicKeyParameters.FromEncoding(ntruParameters, asn1OctetString.GetOctets());
} catch (Exception) {
}
}
throw new ArgumentException("invalid " + ntruParameters.Name + " public key");
}
private static AsymmetricKeyParameter FalconConverter(SubjectPublicKeyInfo keyInfo, object defaultParams)
{
FalconParameters falconParameters = PqcUtilities.FalconParamsLookup(keyInfo.Algorithm.Algorithm);
try {
Asn1Object asn1Object = keyInfo.ParsePublicKey();
if (!(asn1Object is Asn1Sequence)) {
byte[] octets = Asn1OctetString.GetInstance(asn1Object).GetOctets();
if (octets[0] != (byte)falconParameters.LogN)
throw new ArgumentException("byte[] enc of Falcon h value not tagged correctly");
return new FalconPublicKeyParameters(falconParameters, Arrays.CopyOfRange(octets, 1, octets.Length));
}
byte[] octets2 = Asn1OctetString.GetInstance(Asn1Sequence.GetInstance(asn1Object)[0]).GetOctets();
return new FalconPublicKeyParameters(falconParameters, octets2);
} catch (Exception) {
byte[] octets3 = keyInfo.PublicKey.GetOctets();
if (octets3[0] != (byte)falconParameters.LogN)
throw new ArgumentException("byte[] enc of Falcon h value not tagged correctly");
return new FalconPublicKeyParameters(falconParameters, Arrays.CopyOfRange(octets3, 1, octets3.Length));
}
}
private static AsymmetricKeyParameter BikeConverter(SubjectPublicKeyInfo keyInfo, object defaultParams)
{
try {
byte[] octets = Asn1OctetString.GetInstance(keyInfo.ParsePublicKey()).GetOctets();
return new BikePublicKeyParameters(PqcUtilities.BikeParamsLookup(keyInfo.Algorithm.Algorithm), octets);
} catch (Exception) {
byte[] octets2 = keyInfo.PublicKey.GetOctets();
return new BikePublicKeyParameters(PqcUtilities.BikeParamsLookup(keyInfo.Algorithm.Algorithm), octets2);
}
}
private static AsymmetricKeyParameter HqcConverter(SubjectPublicKeyInfo keyInfo, object defaultParams)
{
try {
byte[] octets = Asn1OctetString.GetInstance(keyInfo.ParsePublicKey()).GetOctets();
return new HqcPublicKeyParameters(PqcUtilities.HqcParamsLookup(keyInfo.Algorithm.Algorithm), octets);
} catch (Exception) {
byte[] octets2 = keyInfo.PublicKey.GetOctets();
return new HqcPublicKeyParameters(PqcUtilities.HqcParamsLookup(keyInfo.Algorithm.Algorithm), octets2);
}
}
}
}