summary refs log tree commit diff
diff options
context:
space:
mode:
authorroyb <roy.basmacier@primekey.com>2022-10-24 16:59:53 -0400
committerroyb <roy.basmacier@primekey.com>2022-10-24 16:59:53 -0400
commit7cd4b8af5f4bbfbde9e4b0f3c4b3a6509153869e (patch)
tree083c229288c7ee4f1f96bc97bc5ecb9676a721c9
parentnamespace error (diff)
downloadBouncyCastle.NET-ed25519-7cd4b8af5f4bbfbde9e4b0f3c4b3a6509153869e.tar.xz
Fixed pqc/utils
-rw-r--r--crypto/src/asn1/bc/BCObjectIdentifiers.cs18
-rw-r--r--crypto/src/pqc/crypto/utils/PrivateKeyFactory.cs84
-rw-r--r--crypto/src/pqc/crypto/utils/PrivateKeyInfoFactory.cs158
-rw-r--r--crypto/src/pqc/crypto/utils/PublicKeyFactory.cs233
-rw-r--r--crypto/src/pqc/crypto/utils/SubjectPublicKeyInfoFactory.cs151
5 files changed, 353 insertions, 291 deletions
diff --git a/crypto/src/asn1/bc/BCObjectIdentifiers.cs b/crypto/src/asn1/bc/BCObjectIdentifiers.cs
index 6bfebf132..d526980e5 100644
--- a/crypto/src/asn1/bc/BCObjectIdentifiers.cs
+++ b/crypto/src/asn1/bc/BCObjectIdentifiers.cs
@@ -192,15 +192,15 @@ namespace Org.BouncyCastle.Asn1.BC
         public static readonly DerObjectIdentifier lightsaberkem256r3 = pqc_kem_saber.Branch("7");
         public static readonly DerObjectIdentifier saberkem256r3 = pqc_kem_saber.Branch("8");
         public static readonly DerObjectIdentifier firesaberkem256r3 = pqc_kem_saber.Branch("9");
-       public static readonly DerObjectIdentifier ulightsaberkemr3 = pqc_kem_saber.Branch("10");
-       public static readonly DerObjectIdentifier usaberkemr3 = pqc_kem_saber.Branch("11");
-       public static readonly DerObjectIdentifier ufiresaberkemr3 = pqc_kem_saber.Branch("12");
-       public static readonly DerObjectIdentifier lightsaberkem90sr3 = pqc_kem_saber.Branch("13");
-       public static readonly DerObjectIdentifier saberkem90sr3 = pqc_kem_saber.Branch("14");
-       public static readonly DerObjectIdentifier firesaberkem90sr3 = pqc_kem_saber.Branch("15");
-       public static readonly DerObjectIdentifier ulightsaberkem90sr3 = pqc_kem_saber.Branch("16");
-       public static readonly DerObjectIdentifier usaberkem90sr3 = pqc_kem_saber.Branch("17");
-       public static readonly DerObjectIdentifier ufiresaberkem90sr3 = pqc_kem_saber.Branch("18");
+        public static readonly DerObjectIdentifier ulightsaberkemr3 = pqc_kem_saber.Branch("10");
+        public static readonly DerObjectIdentifier usaberkemr3 = pqc_kem_saber.Branch("11");
+        public static readonly DerObjectIdentifier ufiresaberkemr3 = pqc_kem_saber.Branch("12");
+        public static readonly DerObjectIdentifier lightsaberkem90sr3 = pqc_kem_saber.Branch("13");
+        public static readonly DerObjectIdentifier saberkem90sr3 = pqc_kem_saber.Branch("14");
+        public static readonly DerObjectIdentifier firesaberkem90sr3 = pqc_kem_saber.Branch("15");
+        public static readonly DerObjectIdentifier ulightsaberkem90sr3 = pqc_kem_saber.Branch("16");
+        public static readonly DerObjectIdentifier usaberkem90sr3 = pqc_kem_saber.Branch("17");
+        public static readonly DerObjectIdentifier ufiresaberkem90sr3 = pqc_kem_saber.Branch("18");
 
         /**
          * SIKE
diff --git a/crypto/src/pqc/crypto/utils/PrivateKeyFactory.cs b/crypto/src/pqc/crypto/utils/PrivateKeyFactory.cs
index 8792727b8..7db65dbfb 100644
--- a/crypto/src/pqc/crypto/utils/PrivateKeyFactory.cs
+++ b/crypto/src/pqc/crypto/utils/PrivateKeyFactory.cs
@@ -9,10 +9,12 @@ using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.Utilities;
 using Org.BouncyCastle.Math;
 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.Crystals.Kyber;
 using Org.BouncyCastle.Pqc.Crypto.Falcon;
+using Org.BouncyCastle.Pqc.Crypto.Hqc;
 using Org.BouncyCastle.Pqc.Crypto.Lms;
 using Org.BouncyCastle.Pqc.Crypto.Picnic;
 using Org.BouncyCastle.Pqc.Crypto.Saber;
@@ -22,9 +24,8 @@ using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Pqc.Crypto.Utilities
 {
-    public class PrivateKeyFactory
+    public static class PrivateKeyFactory
     {
-
         /// <summary> Create a private key parameter from a PKCS8 PrivateKeyInfo encoding.</summary>
         /// <param name="privateKeyInfoData"> the PrivateKeyInfo encoding</param>
         /// <returns> a suitable private key parameter</returns>
@@ -43,7 +44,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
             return CreateKey(PrivateKeyInfo.GetInstance(new Asn1InputStream(inStr).ReadObject()));
         }
 
-
         /// <summary> Create a private key parameter from the passed in PKCS8 PrivateKeyInfo object.</summary>
         /// <param name="keyInfo"> the PrivateKeyInfo object containing the key material</param>
         /// <returns> a suitable private key parameter</returns>
@@ -71,7 +71,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
                     return LmsPrivateKeyParameters.GetInstance(Arrays.CopyOfRange(keyEnc, 4, keyEnc.Length));
                 }
             }
-
             if (algOID.On(BCObjectIdentifiers.pqc_kem_mceliece))
             {
                 CmcePrivateKey cmceKey = CmcePrivateKey.GetInstance(keyInfo.ParsePrivateKey());
@@ -79,7 +78,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
 
                 return new CmcePrivateKeyParameters(spParams, cmceKey.Delta, cmceKey.C, cmceKey.G, cmceKey.Alpha, cmceKey.S);
             }
-            
             if (algOID.On(BCObjectIdentifiers.sphincsPlus))
             {
                 byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePrivateKey()).GetOctets();
@@ -108,6 +106,24 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
 
                 return new SikePrivateKeyParameters(sikeParams, keyEnc);
             }
+            if (algOID.On(BCObjectIdentifiers.pqc_kem_bike))
+            {
+                byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePrivateKey()).GetOctets();
+                BikeParameters bikeParams = PqcUtilities.BikeParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm);
+
+                byte[] h0 = Arrays.CopyOfRange(keyEnc, 0, bikeParams.RByte);
+                byte[] h1 = Arrays.CopyOfRange(keyEnc, bikeParams.RByte, 2 * bikeParams.RByte);
+                byte[] sigma = Arrays.CopyOfRange(keyEnc, 2 * bikeParams.RByte, keyEnc.Length);
+
+                return new BikePrivateKeyParameters(bikeParams, h0, h1, sigma);
+            }
+            if (algOID.On(BCObjectIdentifiers.pqc_kem_hqc))
+            {
+                byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePrivateKey()).GetOctets();
+                HqcParameters hqcParams = PqcUtilities.HqcParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm);
+
+                return new HqcPrivateKeyParameters(hqcParams, keyEnc);
+            }
             if (algOID.Equals(BCObjectIdentifiers.kyber512)
                 || algOID.Equals(BCObjectIdentifiers.kyber512_aes)
                 || algOID.Equals(BCObjectIdentifiers.kyber768)
@@ -158,9 +174,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
 
                 int version = DerInteger.GetInstance(keyEnc[0]).Value.IntValue;
                 if (version != 0)
-                {
                     throw new IOException("unknown private key version: " + version);
-                }
 
                 if (keyInfo.PublicKeyData != null)
                 {
@@ -187,39 +201,35 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
                 }
             }
             if (algOID.Equals(BCObjectIdentifiers.falcon_512) || algOID.Equals(BCObjectIdentifiers.falcon_1024))
-                {
-                    Asn1Sequence keyEnc = Asn1Sequence.GetInstance(keyInfo.ParsePrivateKey());
-                    FalconParameters spParams = PqcUtilities.FalconParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm);
+            {
+                Asn1Sequence keyEnc = Asn1Sequence.GetInstance(keyInfo.ParsePrivateKey());
+                FalconParameters spParams = PqcUtilities.FalconParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm);
                     
-                    DerBitString publicKeyData = keyInfo.PublicKeyData;
-                    int version = DerInteger.GetInstance(keyEnc[0]).Value.IntValue;
-                    if (version != 1)
-                    {
-                        throw new IOException("unknown private key version: " + version);
-                    }
+                DerBitString publicKeyData = keyInfo.PublicKeyData;
+                int version = DerInteger.GetInstance(keyEnc[0]).Value.IntValue;
+                if (version != 1)
+                    throw new IOException("unknown private key version: " + version);
 
-                    if (keyInfo.PublicKeyData != null)
-                    {
-                        //ASN1Sequence pubKey = ASN1Sequence.getInstance(keyInfo.getPublicKeyData().getOctets());
-                        return new FalconPrivateKeyParameters(spParams,
-                            Asn1OctetString.GetInstance(keyEnc[1]).GetOctets(),
-                            Asn1OctetString.GetInstance(keyEnc[2]).GetOctets(),
-                            Asn1OctetString.GetInstance(keyEnc[3]).GetOctets(),
-                            publicKeyData.GetOctets()); // encT1
-                    }
-                    else
-                    {
-                        return new FalconPrivateKeyParameters(spParams,
-                            Asn1OctetString.GetInstance(keyEnc[1]).GetOctets(),
-                            Asn1OctetString.GetInstance(keyEnc[2]).GetOctets(),
-                            Asn1OctetString.GetInstance(keyEnc[3]).GetOctets(),
-                            null);
-                    }
+                if (keyInfo.PublicKeyData != null)
+                {
+                    //ASN1Sequence pubKey = ASN1Sequence.getInstance(keyInfo.getPublicKeyData().getOctets());
+                    return new FalconPrivateKeyParameters(spParams,
+                        Asn1OctetString.GetInstance(keyEnc[1]).GetOctets(),
+                        Asn1OctetString.GetInstance(keyEnc[2]).GetOctets(),
+                        Asn1OctetString.GetInstance(keyEnc[3]).GetOctets(),
+                        publicKeyData.GetOctets()); // encT1
                 }
-            
-            
-            throw new Exception("algorithm identifier in private key not recognised");
+                else
+                {
+                    return new FalconPrivateKeyParameters(spParams,
+                        Asn1OctetString.GetInstance(keyEnc[1]).GetOctets(),
+                        Asn1OctetString.GetInstance(keyEnc[2]).GetOctets(),
+                        Asn1OctetString.GetInstance(keyEnc[3]).GetOctets(),
+                        null);
+                }
+            }
 
+            throw new Exception("algorithm identifier in private key not recognised");
         }
     }
-}
\ No newline at end of file
+}
diff --git a/crypto/src/pqc/crypto/utils/PrivateKeyInfoFactory.cs b/crypto/src/pqc/crypto/utils/PrivateKeyInfoFactory.cs
index b43810f13..806eae8b7 100644
--- a/crypto/src/pqc/crypto/utils/PrivateKeyInfoFactory.cs
+++ b/crypto/src/pqc/crypto/utils/PrivateKeyInfoFactory.cs
@@ -5,10 +5,12 @@ using Org.BouncyCastle.Asn1.Pkcs;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto;
 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.Crystals.Kyber;
 using Org.BouncyCastle.Pqc.Crypto.Falcon;
+using Org.BouncyCastle.Pqc.Crypto.Hqc;
 using Org.BouncyCastle.Pqc.Crypto.Lms;
 using Org.BouncyCastle.Pqc.Crypto.Picnic;
 using Org.BouncyCastle.Pqc.Crypto.Saber;
@@ -18,13 +20,8 @@ using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Pqc.Crypto.Utilities
 {
-    public class PrivateKeyInfoFactory
+    public static class PrivateKeyInfoFactory
     {
-        private PrivateKeyInfoFactory()
-        {
-
-        }
-
         /// <summary> Create a PrivateKeyInfo representation of a private key.</summary>
         /// <param name="privateKey"> the key to be encoded into the info object.</param>
         /// <returns> the appropriate PrivateKeyInfo</returns>
@@ -41,135 +38,142 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
         /// <exception cref="ArgumentException"> on an error encoding the key</exception>
         public static PrivateKeyInfo CreatePrivateKeyInfo(AsymmetricKeyParameter privateKey, Asn1Set attributes)
         {
-            if (privateKey is LmsPrivateKeyParameters)
+            if (privateKey is LmsPrivateKeyParameters lmsPrivateKeyParameters)
             {
-                LmsPrivateKeyParameters parameters = (LmsPrivateKeyParameters)privateKey;
-
-                byte[] encoding = Composer.Compose().U32Str(1).Bytes(parameters).Build();
-                byte[] pubEncoding = Composer.Compose().U32Str(1).Bytes(parameters.GetPublicKey()).Build();
+                byte[] encoding = Composer.Compose().U32Str(1).Bytes(lmsPrivateKeyParameters).Build();
+                byte[] pubEncoding = Composer.Compose().U32Str(1).Bytes(lmsPrivateKeyParameters.GetPublicKey()).Build();
 
                 AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdAlgHssLmsHashsig);
                 return new PrivateKeyInfo(algorithmIdentifier, new DerOctetString(encoding), attributes, pubEncoding);
             }
-            if (privateKey is HssPrivateKeyParameters)
+            if (privateKey is HssPrivateKeyParameters hssPrivateKeyParameters)
             {
-                HssPrivateKeyParameters parameters = (HssPrivateKeyParameters)privateKey;
-
-                byte[] encoding = Composer.Compose().U32Str(parameters.L).Bytes(parameters).Build();
-                byte[] pubEncoding = Composer.Compose().U32Str(parameters.L).Bytes(parameters.GetPublicKey().LmsPublicKey).Build();
+                int L = hssPrivateKeyParameters.L;
+                byte[] encoding = Composer.Compose().U32Str(L).Bytes(hssPrivateKeyParameters).Build();
+                byte[] pubEncoding = Composer.Compose().U32Str(L).Bytes(hssPrivateKeyParameters.GetPublicKey().LmsPublicKey).Build();
 
                 AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdAlgHssLmsHashsig);
                 return new PrivateKeyInfo(algorithmIdentifier, new DerOctetString(encoding), attributes, pubEncoding);
             }
-            if (privateKey is SphincsPlusPrivateKeyParameters)
+            if (privateKey is SphincsPlusPrivateKeyParameters sphincsPlusPrivateKeyParameters)
             {
-                SphincsPlusPrivateKeyParameters parameters = (SphincsPlusPrivateKeyParameters)privateKey;
-
-                byte[] encoding = parameters.GetEncoded();
-                byte[] pubEncoding = parameters.GetEncodedPublicKey();
+                byte[] encoding = sphincsPlusPrivateKeyParameters.GetEncoded();
+                byte[] pubEncoding = sphincsPlusPrivateKeyParameters.GetEncodedPublicKey();
 
-                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.SphincsPlusOidLookup(parameters.Parameters));
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.SphincsPlusOidLookup(sphincsPlusPrivateKeyParameters.Parameters));
                 return new PrivateKeyInfo(algorithmIdentifier, new DerOctetString(encoding), attributes, pubEncoding);
             }
-            if (privateKey is CmcePrivateKeyParameters)
+            if (privateKey is CmcePrivateKeyParameters cmcePrivateKeyParameters)
             {
-                CmcePrivateKeyParameters parameters = (CmcePrivateKeyParameters) privateKey;
-
-                byte[] encoding = parameters.GetEncoded();
+                byte[] encoding = cmcePrivateKeyParameters.GetEncoded();
                 AlgorithmIdentifier algorithmIdentifier =
-                    new AlgorithmIdentifier(PqcUtilities.McElieceOidLookup(parameters.Parameters));
+                    new AlgorithmIdentifier(PqcUtilities.McElieceOidLookup(cmcePrivateKeyParameters.Parameters));
 
-                CmcePublicKey CmcePub = new CmcePublicKey(parameters.ReconstructPublicKey());
-                CmcePrivateKey CmcePriv = new CmcePrivateKey(0, parameters.Delta, parameters.C, parameters.G,
-                    parameters.Alpha, parameters.S, CmcePub);
+                CmcePublicKey CmcePub = new CmcePublicKey(cmcePrivateKeyParameters.ReconstructPublicKey());
+                CmcePrivateKey CmcePriv = new CmcePrivateKey(0, cmcePrivateKeyParameters.Delta,
+                    cmcePrivateKeyParameters.C, cmcePrivateKeyParameters.G, cmcePrivateKeyParameters.Alpha,
+                    cmcePrivateKeyParameters.S, CmcePub);
                 return new PrivateKeyInfo(algorithmIdentifier, CmcePriv, attributes);
             }
-            if (privateKey is SaberPrivateKeyParameters)
+            if (privateKey is SaberPrivateKeyParameters saberPrivateKeyParameters)
             {
-                SaberPrivateKeyParameters parameters = (SaberPrivateKeyParameters)privateKey;
+                byte[] encoding = saberPrivateKeyParameters.GetEncoded();
 
-                byte[] encoding = parameters.GetEncoded();
-
-                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.SaberOidLookup(parameters.Parameters));
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.SaberOidLookup(saberPrivateKeyParameters.Parameters));
 
                 return new PrivateKeyInfo(algorithmIdentifier, new DerOctetString(encoding), attributes);
             }
-            if (privateKey is PicnicPrivateKeyParameters)
+            if (privateKey is PicnicPrivateKeyParameters picnicPrivateKeyParameters)
             {
-                PicnicPrivateKeyParameters parameters = (PicnicPrivateKeyParameters)privateKey;
-
-                byte[] encoding = parameters.GetEncoded();
+                byte[] encoding = picnicPrivateKeyParameters.GetEncoded();
 
-                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.PicnicOidLookup(parameters.Parameters));
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.PicnicOidLookup(picnicPrivateKeyParameters.Parameters));
                 return new PrivateKeyInfo(algorithmIdentifier, new DerOctetString(encoding), attributes);
             }
-            if (privateKey is SikePrivateKeyParameters)
+            if (privateKey is SikePrivateKeyParameters sikePrivateKeyParameters)
             {
-                SikePrivateKeyParameters parameters = (SikePrivateKeyParameters)privateKey;
+                byte[] encoding = sikePrivateKeyParameters.GetEncoded();
 
-                byte[] encoding = parameters.GetEncoded();
-
-                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.SikeOidLookup(parameters.Parameters));
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.SikeOidLookup(sikePrivateKeyParameters.Parameters));
                 return new PrivateKeyInfo(algorithmIdentifier, new DerOctetString(encoding), attributes);
             }
-            if (privateKey is FalconPrivateKeyParameters)
+            if (privateKey is FalconPrivateKeyParameters falconPrivateKeyParameters)
             {
-                FalconPrivateKeyParameters parameters = (FalconPrivateKeyParameters)privateKey;
-
                 Asn1EncodableVector v = new Asn1EncodableVector();
 
                 v.Add(new DerInteger(1));
-                v.Add(new DerOctetString(parameters.GetSpolyf()));
-                v.Add(new DerOctetString(parameters.GetG()));
-                v.Add(new DerOctetString(parameters.GetSpolyF()));
+                v.Add(new DerOctetString(falconPrivateKeyParameters.GetSpolyf()));
+                v.Add(new DerOctetString(falconPrivateKeyParameters.GetG()));
+                v.Add(new DerOctetString(falconPrivateKeyParameters.GetSpolyF()));
 
-                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.FalconOidLookup(parameters.Parameters));
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.FalconOidLookup(falconPrivateKeyParameters.Parameters));
 
-                return new PrivateKeyInfo(algorithmIdentifier, new DerSequence(v), attributes, parameters.GetPublicKey());
+                return new PrivateKeyInfo(algorithmIdentifier, new DerSequence(v), attributes,
+                    falconPrivateKeyParameters.GetPublicKey());
             }
-            if (privateKey is KyberPrivateKeyParameters)
+            if (privateKey is KyberPrivateKeyParameters kyberPrivateKeyParameters)
             {
-                KyberPrivateKeyParameters parameters = (KyberPrivateKeyParameters)privateKey;
-            
                 Asn1EncodableVector v = new Asn1EncodableVector();
 
                 v.Add(new DerInteger(0));
-                v.Add(new DerOctetString(parameters.S));
-                v.Add(new DerOctetString(parameters.Hpk));
-                v.Add(new DerOctetString(parameters.Nonce));
+                v.Add(new DerOctetString(kyberPrivateKeyParameters.S));
+                v.Add(new DerOctetString(kyberPrivateKeyParameters.Hpk));
+                v.Add(new DerOctetString(kyberPrivateKeyParameters.Nonce));
 
-                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.KyberOidLookup(parameters.Parameters));
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.KyberOidLookup(kyberPrivateKeyParameters.Parameters));
 
                 Asn1EncodableVector vPub = new Asn1EncodableVector();
-                vPub.Add(new DerOctetString(parameters.T));
-                vPub.Add(new DerOctetString(parameters.Rho));
+                vPub.Add(new DerOctetString(kyberPrivateKeyParameters.T));
+                vPub.Add(new DerOctetString(kyberPrivateKeyParameters.Rho));
 
-                return new PrivateKeyInfo(algorithmIdentifier, new DerSequence(v), attributes, new DerSequence(vPub).GetEncoded());
+                return new PrivateKeyInfo(algorithmIdentifier, new DerSequence(v), attributes,
+                    new DerSequence(vPub).GetEncoded());
             }
-            if (privateKey is DilithiumPrivateKeyParameters)
+            if (privateKey is DilithiumPrivateKeyParameters dilithiumPrivateKeyParameters)
             {
-                DilithiumPrivateKeyParameters parameters = (DilithiumPrivateKeyParameters)privateKey;
-
                 Asn1EncodableVector v = new Asn1EncodableVector();
 
                 v.Add(new DerInteger(0));
-                v.Add(new DerBitString(parameters.Rho));
-                v.Add(new DerBitString(parameters.K));
-                v.Add(new DerBitString(parameters.Tr));
-                v.Add(new DerBitString(parameters.S1));
-                v.Add(new DerBitString(parameters.S2));
-                v.Add(new DerBitString(parameters.T0));
+                v.Add(new DerBitString(dilithiumPrivateKeyParameters.Rho));
+                v.Add(new DerBitString(dilithiumPrivateKeyParameters.K));
+                v.Add(new DerBitString(dilithiumPrivateKeyParameters.Tr));
+                v.Add(new DerBitString(dilithiumPrivateKeyParameters.S1));
+                v.Add(new DerBitString(dilithiumPrivateKeyParameters.S2));
+                v.Add(new DerBitString(dilithiumPrivateKeyParameters.T0));
 
-                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.DilithiumOidLookup(parameters.Parameters));
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.DilithiumOidLookup(dilithiumPrivateKeyParameters.Parameters));
 
                 Asn1EncodableVector vPub = new Asn1EncodableVector();
-                vPub.Add(new DerOctetString(parameters.Rho));
-                vPub.Add(new DerOctetString(parameters.T1));
+                vPub.Add(new DerOctetString(dilithiumPrivateKeyParameters.Rho));
+                vPub.Add(new DerOctetString(dilithiumPrivateKeyParameters.T1));
+
+                return new PrivateKeyInfo(algorithmIdentifier, new DerSequence(v), attributes,
+                    new DerSequence(vPub).GetEncoded());
+            }
+            if (privateKey is BikePrivateKeyParameters bikePrivateKeyParameters)
+            {
+                byte[] encoding = bikePrivateKeyParameters.GetEncoded();
 
-                return new PrivateKeyInfo(algorithmIdentifier, new DerSequence(v), attributes, new DerSequence(vPub).GetEncoded());
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.BikeOidLookup(bikePrivateKeyParameters.Parameters));
+                return new PrivateKeyInfo(algorithmIdentifier, new DerOctetString(encoding), attributes);
+            }
+            else if (privateKey is HqcPrivateKeyParameters hqcPrivateKeyParameters)
+            {
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.HqcOidLookup(hqcPrivateKeyParameters.Parameters));
+                byte[] encoding = hqcPrivateKeyParameters.PrivateKey;
+                return new PrivateKeyInfo(algorithmIdentifier, new DerOctetString(encoding), attributes);
             }
 
             throw new ArgumentException("Class provided is not convertible: " + Platform.GetTypeName(privateKey));
         }
     }
-}
\ No newline at end of file
+}
diff --git a/crypto/src/pqc/crypto/utils/PublicKeyFactory.cs b/crypto/src/pqc/crypto/utils/PublicKeyFactory.cs
index bb33a3aa3..5d55a73aa 100644
--- a/crypto/src/pqc/crypto/utils/PublicKeyFactory.cs
+++ b/crypto/src/pqc/crypto/utils/PublicKeyFactory.cs
@@ -4,15 +4,19 @@ using System.IO;
 
 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.Math;
 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.Crystals.Kyber;
 using Org.BouncyCastle.Pqc.Crypto.Falcon;
+using Org.BouncyCastle.Pqc.Crypto.Hqc;
+using Org.BouncyCastle.Pqc.Crypto.Lms;
 using Org.BouncyCastle.Pqc.Crypto.Picnic;
 using Org.BouncyCastle.Pqc.Crypto.Saber;
 using Org.BouncyCastle.Pqc.Crypto.Sike;
@@ -21,89 +25,99 @@ using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Pqc.Crypto.Utilities
 {
-    public class PublicKeyFactory
+    public static class PublicKeyFactory
     {
-        private static Dictionary<DerObjectIdentifier, SubjectPublicKeyInfoConverter> converters = new Dictionary<DerObjectIdentifier, SubjectPublicKeyInfoConverter>();
-
+        private static Dictionary<DerObjectIdentifier, SubjectPublicKeyInfoConverter> Converters =
+            new Dictionary<DerObjectIdentifier, SubjectPublicKeyInfoConverter>();
 
         static PublicKeyFactory()
         {
-            converters[BCObjectIdentifiers.sphincsPlus] = new SphincsPlusConverter();
-            converters[BCObjectIdentifiers.sphincsPlus_shake_256] = new SphincsPlusConverter();
-            converters[BCObjectIdentifiers.sphincsPlus_sha_256] = new SphincsPlusConverter();
-            converters[BCObjectIdentifiers.sphincsPlus_sha_512] = new SphincsPlusConverter();
+            Converters[PkcsObjectIdentifiers.IdAlgHssLmsHashsig] = new LmsConverter();
+
+            Converters[BCObjectIdentifiers.sphincsPlus] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_shake_256] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_sha_256] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_sha_512] = new SphincsPlusConverter();
             
-            converters[BCObjectIdentifiers.mceliece348864_r3] = new CmceConverter();
-            converters[BCObjectIdentifiers.mceliece348864f_r3] = new CmceConverter();
-            converters[BCObjectIdentifiers.mceliece460896_r3] = new CmceConverter();
-            converters[BCObjectIdentifiers.mceliece460896f_r3] = new CmceConverter();
-            converters[BCObjectIdentifiers.mceliece6688128_r3] = new CmceConverter();
-            converters[BCObjectIdentifiers.mceliece6688128f_r3] = new CmceConverter();
-            converters[BCObjectIdentifiers.mceliece6960119_r3] = new CmceConverter();
-            converters[BCObjectIdentifiers.mceliece6960119f_r3] = new CmceConverter();
-            converters[BCObjectIdentifiers.mceliece8192128_r3] = new CmceConverter();
-            converters[BCObjectIdentifiers.mceliece8192128f_r3] = new CmceConverter();
+            Converters[BCObjectIdentifiers.mceliece348864_r3] = new CmceConverter();
+            Converters[BCObjectIdentifiers.mceliece348864f_r3] = new CmceConverter();
+            Converters[BCObjectIdentifiers.mceliece460896_r3] = new CmceConverter();
+            Converters[BCObjectIdentifiers.mceliece460896f_r3] = new CmceConverter();
+            Converters[BCObjectIdentifiers.mceliece6688128_r3] = new CmceConverter();
+            Converters[BCObjectIdentifiers.mceliece6688128f_r3] = new CmceConverter();
+            Converters[BCObjectIdentifiers.mceliece6960119_r3] = new CmceConverter();
+            Converters[BCObjectIdentifiers.mceliece6960119f_r3] = new CmceConverter();
+            Converters[BCObjectIdentifiers.mceliece8192128_r3] = new CmceConverter();
+            Converters[BCObjectIdentifiers.mceliece8192128f_r3] = new CmceConverter();
            
-            converters[BCObjectIdentifiers.lightsaberkem128r3] = new SaberConverter();
-            converters[BCObjectIdentifiers.saberkem128r3] = new SaberConverter();
-            converters[BCObjectIdentifiers.firesaberkem128r3] = new SaberConverter();
-            converters[BCObjectIdentifiers.lightsaberkem192r3] = new SaberConverter();
-            converters[BCObjectIdentifiers.saberkem192r3] = new SaberConverter();
-            converters[BCObjectIdentifiers.firesaberkem192r3] = new SaberConverter();
-            converters[BCObjectIdentifiers.lightsaberkem256r3] = new SaberConverter();
-            converters[BCObjectIdentifiers.saberkem256r3] = new SaberConverter();
-            converters[BCObjectIdentifiers.firesaberkem256r3] = new SaberConverter();
-            converters[BCObjectIdentifiers.ulightsaberkemr3] = new SaberConverter();
-            converters[BCObjectIdentifiers.usaberkemr3] = new SaberConverter();
-            converters[BCObjectIdentifiers.ufiresaberkemr3] = new SaberConverter();
-            converters[BCObjectIdentifiers.lightsaberkem90sr3] = new SaberConverter();
-            converters[BCObjectIdentifiers.saberkem90sr3] = new SaberConverter();
-            converters[BCObjectIdentifiers.firesaberkem90sr3] = new SaberConverter();
-            converters[BCObjectIdentifiers.ulightsaberkem90sr3] = new SaberConverter();
-            converters[BCObjectIdentifiers.usaberkem90sr3] = new SaberConverter();
-            converters[BCObjectIdentifiers.ufiresaberkem90sr3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.lightsaberkem128r3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.saberkem128r3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.firesaberkem128r3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.lightsaberkem192r3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.saberkem192r3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.firesaberkem192r3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.lightsaberkem256r3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.saberkem256r3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.firesaberkem256r3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.ulightsaberkemr3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.usaberkemr3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.ufiresaberkemr3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.lightsaberkem90sr3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.saberkem90sr3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.firesaberkem90sr3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.ulightsaberkem90sr3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.usaberkem90sr3] = new SaberConverter();
+            Converters[BCObjectIdentifiers.ufiresaberkem90sr3] = new SaberConverter();
             
-            converters[BCObjectIdentifiers.picnic] = new PicnicConverter();
-            converters[BCObjectIdentifiers.picnicl1fs] = new PicnicConverter();
-            converters[BCObjectIdentifiers.picnicl1ur] = new PicnicConverter();
-            converters[BCObjectIdentifiers.picnicl3fs] = new PicnicConverter();
-            converters[BCObjectIdentifiers.picnicl3ur] = new PicnicConverter();
-            converters[BCObjectIdentifiers.picnicl5fs] = new PicnicConverter();
-            converters[BCObjectIdentifiers.picnicl5ur] = new PicnicConverter();
-            converters[BCObjectIdentifiers.picnic3l1] = new PicnicConverter();
-            converters[BCObjectIdentifiers.picnic3l3] = new PicnicConverter();
-            converters[BCObjectIdentifiers.picnic3l5] = new PicnicConverter();
-            converters[BCObjectIdentifiers.picnicl1full] = new PicnicConverter();
-            converters[BCObjectIdentifiers.picnicl3full] = new PicnicConverter();
-            converters[BCObjectIdentifiers.picnicl5full] = new PicnicConverter();
+            Converters[BCObjectIdentifiers.picnic] = new PicnicConverter();
+            Converters[BCObjectIdentifiers.picnicl1fs] = new PicnicConverter();
+            Converters[BCObjectIdentifiers.picnicl1ur] = new PicnicConverter();
+            Converters[BCObjectIdentifiers.picnicl3fs] = new PicnicConverter();
+            Converters[BCObjectIdentifiers.picnicl3ur] = new PicnicConverter();
+            Converters[BCObjectIdentifiers.picnicl5fs] = new PicnicConverter();
+            Converters[BCObjectIdentifiers.picnicl5ur] = new PicnicConverter();
+            Converters[BCObjectIdentifiers.picnic3l1] = new PicnicConverter();
+            Converters[BCObjectIdentifiers.picnic3l3] = new PicnicConverter();
+            Converters[BCObjectIdentifiers.picnic3l5] = new PicnicConverter();
+            Converters[BCObjectIdentifiers.picnicl1full] = new PicnicConverter();
+            Converters[BCObjectIdentifiers.picnicl3full] = new PicnicConverter();
+            Converters[BCObjectIdentifiers.picnicl5full] = new PicnicConverter();
             
-            converters[BCObjectIdentifiers.sikep434] = new SikeConverter();
-            converters[BCObjectIdentifiers.sikep503] = new SikeConverter();
-            converters[BCObjectIdentifiers.sikep610] = new SikeConverter();
-            converters[BCObjectIdentifiers.sikep751] = new SikeConverter();
-            converters[BCObjectIdentifiers.sikep434_compressed] = new SikeConverter();
-            converters[BCObjectIdentifiers.sikep503_compressed] = new SikeConverter();
-            converters[BCObjectIdentifiers.sikep610_compressed] = new SikeConverter();
-            converters[BCObjectIdentifiers.sikep751_compressed] = new SikeConverter();
+            Converters[BCObjectIdentifiers.sikep434] = new SikeConverter();
+            Converters[BCObjectIdentifiers.sikep503] = new SikeConverter();
+            Converters[BCObjectIdentifiers.sikep610] = new SikeConverter();
+            Converters[BCObjectIdentifiers.sikep751] = new SikeConverter();
+            Converters[BCObjectIdentifiers.sikep434_compressed] = new SikeConverter();
+            Converters[BCObjectIdentifiers.sikep503_compressed] = new SikeConverter();
+            Converters[BCObjectIdentifiers.sikep610_compressed] = new SikeConverter();
+            Converters[BCObjectIdentifiers.sikep751_compressed] = new SikeConverter();
             
-            converters[BCObjectIdentifiers.dilithium2] = new DilithiumConverter();
-            converters[BCObjectIdentifiers.dilithium3] = new DilithiumConverter();
-            converters[BCObjectIdentifiers.dilithium5] = new DilithiumConverter();
-            converters[BCObjectIdentifiers.dilithium2_aes] = new DilithiumConverter();
-            converters[BCObjectIdentifiers.dilithium3_aes] = new DilithiumConverter();
-            converters[BCObjectIdentifiers.dilithium5_aes] = new DilithiumConverter();
+            Converters[BCObjectIdentifiers.dilithium2] = new DilithiumConverter();
+            Converters[BCObjectIdentifiers.dilithium3] = new DilithiumConverter();
+            Converters[BCObjectIdentifiers.dilithium5] = new DilithiumConverter();
+            Converters[BCObjectIdentifiers.dilithium2_aes] = new DilithiumConverter();
+            Converters[BCObjectIdentifiers.dilithium3_aes] = new DilithiumConverter();
+            Converters[BCObjectIdentifiers.dilithium5_aes] = new DilithiumConverter();
             
-            converters[BCObjectIdentifiers.falcon_512] = new FalconConverter();
-            converters[BCObjectIdentifiers.falcon_1024] = new FalconConverter();
+            Converters[BCObjectIdentifiers.falcon_512] = new FalconConverter();
+            Converters[BCObjectIdentifiers.falcon_1024] = new FalconConverter();
             
-            converters[BCObjectIdentifiers.kyber512] = new KyberConverter();
-            converters[BCObjectIdentifiers.kyber512_aes] = new KyberConverter();
-            converters[BCObjectIdentifiers.kyber768] = new KyberConverter();
-            converters[BCObjectIdentifiers.kyber768_aes] = new KyberConverter();
-            converters[BCObjectIdentifiers.kyber1024] = new KyberConverter();
-            converters[BCObjectIdentifiers.kyber1024_aes] = new KyberConverter();
+            Converters[BCObjectIdentifiers.kyber512] = new KyberConverter();
+            Converters[BCObjectIdentifiers.kyber512_aes] = new KyberConverter();
+            Converters[BCObjectIdentifiers.kyber768] = new KyberConverter();
+            Converters[BCObjectIdentifiers.kyber768_aes] = new KyberConverter();
+            Converters[BCObjectIdentifiers.kyber1024] = new KyberConverter();
+            Converters[BCObjectIdentifiers.kyber1024_aes] = new KyberConverter();
+
+            Converters[BCObjectIdentifiers.bike128] = new BikeConverter();
+            Converters[BCObjectIdentifiers.bike192] = new BikeConverter();
+            Converters[BCObjectIdentifiers.bike256] = new BikeConverter();
+
+            Converters[BCObjectIdentifiers.hqc128] = new HqcConverter();
+            Converters[BCObjectIdentifiers.hqc192] = new HqcConverter();
+            Converters[BCObjectIdentifiers.hqc256] = new HqcConverter();
         }
-        
+
         /// <summary> Create a public key from a SubjectPublicKeyInfo encoding</summary>
         /// <param name="keyInfoData"> the SubjectPublicKeyInfo encoding</param>
         /// <returns> the appropriate key parameter</returns>
@@ -136,10 +150,10 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
         /// <param name="defaultParams"> default parameters that might be needed.</param>
         /// <returns> the appropriate key parameter</returns>
         /// <exception cref="IOException"> on an error decoding the key</exception>
-        public static AsymmetricKeyParameter CreateKey(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+        public static AsymmetricKeyParameter CreateKey(SubjectPublicKeyInfo keyInfo, object defaultParams)
         {
             AlgorithmIdentifier algId = keyInfo.AlgorithmID;
-            SubjectPublicKeyInfoConverter converter = (SubjectPublicKeyInfoConverter)converters[algId.Algorithm];
+            SubjectPublicKeyInfoConverter converter = (SubjectPublicKeyInfoConverter)Converters[algId.Algorithm];
 
             if (converter != null)
             {
@@ -152,13 +166,36 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
         }
         private abstract class SubjectPublicKeyInfoConverter
         {
-            internal abstract AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams);
+            internal abstract AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, object defaultParams);
         }
-        
+
+        private class LmsConverter
+        :   SubjectPublicKeyInfoConverter
+        {
+            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, object defaultParams)
+            {
+                byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePublicKey()).GetOctets();
+
+                if (Pack.BE_To_UInt32(keyEnc, 0) == 1U)
+                {
+                    return LmsPublicKeyParameters.GetInstance(Arrays.CopyOfRange(keyEnc, 4, keyEnc.Length));
+                }
+                else
+                {
+                    // public key with extra tree height
+                    if (keyEnc.Length == 64)
+                    {
+                        keyEnc = Arrays.CopyOfRange(keyEnc, 4, keyEnc.Length);
+                    }
+                    return HssPublicKeyParameters.GetInstance(keyEnc);
+                }
+            }
+        }
+
         private class SphincsPlusConverter
             : SubjectPublicKeyInfoConverter
         {
-            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, object defaultParams)
             {
             byte[] keyEnc = DerOctetString.GetInstance(keyInfo.ParsePublicKey()).GetOctets();
 
@@ -171,7 +208,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
         private class CmceConverter
             : SubjectPublicKeyInfoConverter
         {
-            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, object defaultParams)
             {
                 byte[] keyEnc = CmcePublicKey.GetInstance(keyInfo.ParsePublicKey()).T;
 
@@ -184,21 +221,21 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
         private class SaberConverter
             : SubjectPublicKeyInfoConverter
         {
-            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, object defaultParams)
             {
                 byte[] keyEnc = DerOctetString.GetInstance(
                     DerSequence.GetInstance(keyInfo.ParsePublicKey())[0]).GetOctets();
 
                 SaberParameters saberParams = PqcUtilities.SaberParamsLookup(keyInfo.AlgorithmID.Algorithm);
 
-                    return new SaberPublicKeyParameters(saberParams, keyEnc);
+                return new SaberPublicKeyParameters(saberParams, keyEnc);
             }
         }
         
         private class PicnicConverter
             : SubjectPublicKeyInfoConverter
         {
-            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, object defaultParams)
             {
                 byte[] keyEnc = DerOctetString.GetInstance(keyInfo.ParsePublicKey()).GetOctets();
 
@@ -210,7 +247,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
         private class SikeConverter
             : SubjectPublicKeyInfoConverter
         {
-            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, object defaultParams)
             {
                 byte[] keyEnc = DerOctetString.GetInstance(keyInfo.ParsePublicKey()).GetOctets();
 
@@ -222,7 +259,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
         private class DilithiumConverter
             : SubjectPublicKeyInfoConverter
         {
-            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, object defaultParams)
             {
                 DilithiumParameters dilithiumParams = PqcUtilities.DilithiumParamsLookup(keyInfo.AlgorithmID.Algorithm);
 
@@ -247,7 +284,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
         private class KyberConverter
             : SubjectPublicKeyInfoConverter
         {
-            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, object defaultParams)
             {
                 KyberParameters kyberParameters = PqcUtilities.KyberParamsLookup(keyInfo.AlgorithmID.Algorithm);
 
@@ -268,11 +305,11 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
                 }
             }
         }
-        
+
         private class FalconConverter 
             : SubjectPublicKeyInfoConverter
         {
-            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, object defaultParams)
             {
                 FalconParameters falconParams = PqcUtilities.FalconParamsLookup(keyInfo.AlgorithmID.Algorithm);
 
@@ -296,5 +333,29 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
                 }
             }
         }
+
+        private class BikeConverter: SubjectPublicKeyInfoConverter
+        {
+            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, object defaultParams)
+            {
+                byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePublicKey()).GetOctets();
+
+                BikeParameters bikeParams = PqcUtilities.BikeParamsLookup(keyInfo.AlgorithmID.Algorithm);
+
+                return new BikePublicKeyParameters(bikeParams, keyEnc);
+            }
+        }
+
+        private class HqcConverter : SubjectPublicKeyInfoConverter
+        {
+            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, object defaultParams)
+            {
+                byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePublicKey()).GetOctets();
+
+                HqcParameters hqcParams = PqcUtilities.HqcParamsLookup(keyInfo.AlgorithmID.Algorithm);
+
+                return new HqcPublicKeyParameters(hqcParams, keyEnc);
+            }
+        }
     }
-}
\ No newline at end of file
+}
diff --git a/crypto/src/pqc/crypto/utils/SubjectPublicKeyInfoFactory.cs b/crypto/src/pqc/crypto/utils/SubjectPublicKeyInfoFactory.cs
index d9800165b..39d437320 100644
--- a/crypto/src/pqc/crypto/utils/SubjectPublicKeyInfoFactory.cs
+++ b/crypto/src/pqc/crypto/utils/SubjectPublicKeyInfoFactory.cs
@@ -1,14 +1,17 @@
 using System;
 
 using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Math;
 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.Crystals.Kyber;
 using Org.BouncyCastle.Pqc.Crypto.Falcon;
+using Org.BouncyCastle.Pqc.Crypto.Hqc;
+using Org.BouncyCastle.Pqc.Crypto.Lms;
 using Org.BouncyCastle.Pqc.Crypto.Picnic;
 using Org.BouncyCastle.Pqc.Crypto.Saber;
 using Org.BouncyCastle.Pqc.Crypto.Sike;
@@ -17,143 +20,127 @@ using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Pqc.Crypto.Utilities
 {
-    
     /// <summary>
     /// A factory to produce Public Key Info Objects.
     /// </summary>
-    public class SubjectPublicKeyInfoFactory
+    public static class SubjectPublicKeyInfoFactory
     {
-        private SubjectPublicKeyInfoFactory()
-        {
-        }
-
         /// <summary>
         /// Create a Subject Public Key Info object for a given public key.
         /// </summary>
         /// <param name="publicKey">One of ElGammalPublicKeyParameters, DSAPublicKeyParameter, DHPublicKeyParameters, RsaKeyParameters or ECPublicKeyParameters</param>
         /// <returns>A subject public key info object.</returns>
         /// <exception cref="Exception">Throw exception if object provided is not one of the above.</exception>
-        public static SubjectPublicKeyInfo CreateSubjectPublicKeyInfo(
-            AsymmetricKeyParameter publicKey)
+        public static SubjectPublicKeyInfo CreateSubjectPublicKeyInfo(AsymmetricKeyParameter publicKey)
         {
             if (publicKey == null)
                 throw new ArgumentNullException("publicKey");
             if (publicKey.IsPrivate)
                 throw new ArgumentException("Private key passed - public key expected.", "publicKey");
-            
-            if (publicKey is SphincsPlusPublicKeyParameters)
+
+            if (publicKey is LmsPublicKeyParameters lmsPublicKeyParameters)
             {
-                SphincsPlusPublicKeyParameters parameters = (SphincsPlusPublicKeyParameters)publicKey;
+                byte[] encoding = Composer.Compose().U32Str(1).Bytes(lmsPublicKeyParameters).Build();
 
-                byte[] encoding = parameters.GetEncoded();
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdAlgHssLmsHashsig);
+                return new SubjectPublicKeyInfo(algorithmIdentifier, new DerOctetString(encoding));
+            }
+            if (publicKey is HssPublicKeyParameters hssPublicKeyParameters)
+            {
+                int L = hssPublicKeyParameters.L;
+                byte[] encoding = Composer.Compose().U32Str(L).Bytes(hssPublicKeyParameters.LmsPublicKey).Build();
 
-                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.SphincsPlusOidLookup(parameters.Parameters));
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdAlgHssLmsHashsig);
                 return new SubjectPublicKeyInfo(algorithmIdentifier, new DerOctetString(encoding));
             }
-            if (publicKey is CmcePublicKeyParameters)
+            if (publicKey is SphincsPlusPublicKeyParameters sphincsPlusPublicKeyParameters)
             {
-                CmcePublicKeyParameters key = (CmcePublicKeyParameters)publicKey;
+                byte[] encoding = sphincsPlusPublicKeyParameters.GetEncoded();
 
-                byte[] encoding = key.GetEncoded();
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.SphincsPlusOidLookup(sphincsPlusPublicKeyParameters.Parameters));
+                return new SubjectPublicKeyInfo(algorithmIdentifier, new DerOctetString(encoding));
+            }
+            if (publicKey is CmcePublicKeyParameters cmcePublicKeyParameters)
+            {
+                byte[] encoding = cmcePublicKeyParameters.GetEncoded();
 
-                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.McElieceOidLookup(key.Parameters));
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.McElieceOidLookup(cmcePublicKeyParameters.Parameters));
 
                 // https://datatracker.ietf.org/doc/draft-uni-qsckeys/
                 return new SubjectPublicKeyInfo(algorithmIdentifier, new CmcePublicKey(encoding));
             }
-            if (publicKey is SaberPublicKeyParameters)
+            if (publicKey is SaberPublicKeyParameters saberPublicKeyParameters)
             {
-                SaberPublicKeyParameters parameters = (SaberPublicKeyParameters)publicKey;
-
-                byte[] encoding = parameters.GetEncoded();
+                byte[] encoding = saberPublicKeyParameters.GetEncoded();
 
-                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.SaberOidLookup(parameters.Parameters));
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.SaberOidLookup(saberPublicKeyParameters.Parameters));
 
                 // https://datatracker.ietf.org/doc/draft-uni-qsckeys/
                 return new SubjectPublicKeyInfo(algorithmIdentifier, new DerSequence(new DerOctetString(encoding)));
             }
-            if (publicKey is PicnicPublicKeyParameters)
+            if (publicKey is PicnicPublicKeyParameters picnicPublicKeyParameters)
             {
-                PicnicPublicKeyParameters parameters = (PicnicPublicKeyParameters)publicKey;
+                byte[] encoding = picnicPublicKeyParameters.GetEncoded();
 
-                byte[] encoding = parameters.GetEncoded();
-
-                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.PicnicOidLookup(parameters.Parameters));
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.PicnicOidLookup(picnicPublicKeyParameters.Parameters));
                 return new SubjectPublicKeyInfo(algorithmIdentifier, new DerOctetString(encoding));
             }
-            if (publicKey is SikePublicKeyParameters)
+            if (publicKey is SikePublicKeyParameters sikePublicKeyParameters)
             {
-                SikePublicKeyParameters parameters = (SikePublicKeyParameters)publicKey;
-
-                byte[] encoding = parameters.GetEncoded();
+                byte[] encoding = sikePublicKeyParameters.GetEncoded();
 
-                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.SikeOidLookup(parameters.Parameters));
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.SikeOidLookup(sikePublicKeyParameters.Parameters));
                 return new SubjectPublicKeyInfo(algorithmIdentifier, new DerOctetString(encoding));
             }
-            if (publicKey is FalconPublicKeyParameters)
+            if (publicKey is FalconPublicKeyParameters falconPublicKeyParameters)
             {
-                FalconPublicKeyParameters parameters = (FalconPublicKeyParameters)publicKey;
-
-                byte[] encoding = parameters.GetEncoded();
-                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.FalconOidLookup(parameters.Parameters));
+                byte[] encoding = falconPublicKeyParameters.GetEncoded();
 
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.FalconOidLookup(falconPublicKeyParameters.Parameters));
                 return new SubjectPublicKeyInfo(algorithmIdentifier, new DerSequence(new DerOctetString(encoding)));
             }
-            if (publicKey is KyberPublicKeyParameters)
+            if (publicKey is KyberPublicKeyParameters kyberPublicKeyParameters)
             {
-                KyberPublicKeyParameters parameters = (KyberPublicKeyParameters)publicKey;
-
-                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.KyberOidLookup(parameters.Parameters));
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.KyberOidLookup(kyberPublicKeyParameters.Parameters));
                 Asn1EncodableVector v = new Asn1EncodableVector();
-                v.Add(new DerOctetString(parameters.T));
-                v.Add(new DerOctetString(parameters.Rho));
+                v.Add(new DerOctetString(kyberPublicKeyParameters.T));
+                v.Add(new DerOctetString(kyberPublicKeyParameters.Rho));
                 return new SubjectPublicKeyInfo(algorithmIdentifier, new DerSequence(v));
             }
-            if (publicKey is DilithiumPublicKeyParameters)
+            if (publicKey is DilithiumPublicKeyParameters dilithiumPublicKeyParameters)
             {
-                DilithiumPublicKeyParameters parameters = (DilithiumPublicKeyParameters)publicKey;
-
-                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.DilithiumOidLookup(parameters.Parameters));
-                Asn1EncodableVector v = new Asn1EncodableVector();
-                v.Add(new DerOctetString(parameters.Rho));
-                v.Add(new DerOctetString(parameters.T1));
-                return new SubjectPublicKeyInfo(algorithmIdentifier, new DerSequence(v));
-            }
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.DilithiumOidLookup(dilithiumPublicKeyParameters.Parameters));
             
-            throw new ArgumentException("Class provided no convertible: " + Platform.GetTypeName(publicKey));
-
-        }
-        
-        private static void ExtractBytes(
-            byte[]		encKey,
-            int			offset,
-            BigInteger	bI)
-        {
-            byte[] val = bI.ToByteArray();
-            int n = (bI.BitLength + 7) / 8;
+                return new SubjectPublicKeyInfo(algorithmIdentifier,
+                    new DerOctetString(Arrays.Concatenate(dilithiumPublicKeyParameters.Rho, dilithiumPublicKeyParameters.T1)));
+            }
+            if (publicKey is BikePublicKeyParameters bikePublicKeyParameters)
+            { 
+                byte[] encoding = bikePublicKeyParameters.GetEncoded();
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.BikeOidLookup(bikePublicKeyParameters.Parameters));
 
-            for (int i = 0; i < n; ++i)
-            {
-                encKey[offset + i] = val[val.Length - 1 - i];
+                return new SubjectPublicKeyInfo(algorithmIdentifier, new DerOctetString(encoding));
             }
-        }
+            if (publicKey is HqcPublicKeyParameters hqcPublicKeyParameters)
+            {
+                byte[] encoding = hqcPublicKeyParameters.GetEncoded();
 
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
+                    PqcUtilities.HqcOidLookup(hqcPublicKeyParameters.Parameters));
 
-        private static void ExtractBytes(byte[] encKey, int size, int offSet, BigInteger bI)
-        {
-            byte[] val = bI.ToByteArray();
-            if (val.Length < size)
-            {
-                byte[] tmp = new byte[size];
-                Array.Copy(val, 0, tmp, tmp.Length - val.Length, val.Length);
-                val = tmp;
+                return new SubjectPublicKeyInfo(algorithmIdentifier, new DerOctetString(encoding));
             }
 
-            for (int i = 0; i != size; i++)
-            {
-                encKey[offSet + i] = val[val.Length - 1 - i];
-            }
+            throw new ArgumentException("Class provided no convertible: " + Platform.GetTypeName(publicKey));
         }
-
     }
-}
\ No newline at end of file
+}