summary refs log tree commit diff
diff options
context:
space:
mode:
authorroyb <roy.basmacier@primekey.com>2022-09-29 18:30:54 -0400
committerroyb <roy.basmacier@primekey.com>2022-09-29 18:30:54 -0400
commite079a4d5b24a1daece4abf8807670da7442fded2 (patch)
tree17e610253993704f30af7b65253ea5ae6a200e49
parentAdded Kyber AES support (diff)
downloadBouncyCastle.NET-ed25519-e079a4d5b24a1daece4abf8807670da7442fded2.tar.xz
Added ASN.1 key encoding/decoding for Kyber, Dilithium, and Falcon.
-rw-r--r--crypto/src/asn1/bc/BCObjectIdentifiers.cs33
-rw-r--r--crypto/src/pqc/crypto/crystals/dilithium/DilithiumPrivateKeyParameters.cs36
-rw-r--r--crypto/src/pqc/crypto/crystals/dilithium/DilithiumPublicKeyParameters.cs11
-rw-r--r--crypto/src/pqc/crypto/crystals/kyber/KyberPrivateKeyParameters.cs7
-rw-r--r--crypto/src/pqc/crypto/crystals/kyber/KyberPublicKeyParameters.cs3
-rw-r--r--crypto/src/pqc/crypto/falcon/FalconKeyPairGenerator.cs11
-rw-r--r--crypto/src/pqc/crypto/falcon/FalconNIST.cs65
-rw-r--r--crypto/src/pqc/crypto/falcon/FalconPrivateKeyParameters.cs34
-rw-r--r--crypto/src/pqc/crypto/utils/PqcUtilities.cs83
-rw-r--r--crypto/src/pqc/crypto/utils/PrivateKeyFactory.cs111
-rw-r--r--crypto/src/pqc/crypto/utils/PrivateKeyInfoFactory.cs59
-rw-r--r--crypto/src/pqc/crypto/utils/PublicKeyFactory.cs97
-rw-r--r--crypto/src/pqc/crypto/utils/SubjectPublicKeyInfoFactory.cs32
-rw-r--r--crypto/test/src/pqc/crypto/test/FalconTest.cs55
14 files changed, 509 insertions, 128 deletions
diff --git a/crypto/src/asn1/bc/BCObjectIdentifiers.cs b/crypto/src/asn1/bc/BCObjectIdentifiers.cs
index a649e0c73..0a2db9fd6 100644
--- a/crypto/src/asn1/bc/BCObjectIdentifiers.cs
+++ b/crypto/src/asn1/bc/BCObjectIdentifiers.cs
@@ -116,6 +116,27 @@ namespace Org.BouncyCastle.Asn1.BC
         public static readonly DerObjectIdentifier picnicl1full = picnic.Branch("10");
         public static readonly DerObjectIdentifier picnicl3full = picnic.Branch("11");
         public static readonly DerObjectIdentifier picnicl5full = picnic.Branch("12");
+        
+        /*
+         * Falcon
+         */
+        public static readonly DerObjectIdentifier falcon = bc_sig.Branch("7");
+
+        public static readonly DerObjectIdentifier falcon_512 = new DerObjectIdentifier("1.3.9999.3.1");  // falcon.branch("1");
+        public static readonly DerObjectIdentifier falcon_1024 =  new DerObjectIdentifier("1.3.9999.3.4"); // falcon.branch("2");
+
+        /*
+         * Dilithium
+         */
+        public static readonly DerObjectIdentifier dilithium = bc_sig.Branch("8");
+
+        // OpenSSL OIDs
+        public static readonly DerObjectIdentifier dilithium2 = new DerObjectIdentifier("1.3.6.1.4.1.2.267.7.4.4"); // dilithium.branch("1");
+        public static readonly DerObjectIdentifier dilithium3 = new DerObjectIdentifier("1.3.6.1.4.1.2.267.7.6.5"); // dilithium.branch("2");
+        public static readonly DerObjectIdentifier dilithium5 = new DerObjectIdentifier("1.3.6.1.4.1.2.267.7.8.7"); // dilithium.branch("3");
+        public static readonly DerObjectIdentifier dilithium2_aes = new DerObjectIdentifier("1.3.6.1.4.1.2.267.11.4.4"); // dilithium.branch("4");
+        public static readonly DerObjectIdentifier dilithium3_aes = new DerObjectIdentifier("1.3.6.1.4.1.2.267.11.6.5"); // dilithium.branch("5");
+        public static readonly DerObjectIdentifier dilithium5_aes = new DerObjectIdentifier("1.3.6.1.4.1.2.267.11.8.7"); // dilithium.branch("6");
 
 
         /**
@@ -184,5 +205,17 @@ namespace Org.BouncyCastle.Asn1.BC
         public static readonly DerObjectIdentifier sikep503_compressed = pqc_kem_sike.Branch("6");
         public static readonly DerObjectIdentifier sikep610_compressed = pqc_kem_sike.Branch("7");
         public static readonly DerObjectIdentifier sikep751_compressed = pqc_kem_sike.Branch("8");
+        
+        /**
+     * Kyber
+     */
+        public static readonly DerObjectIdentifier pqc_kem_kyber = bc_kem.Branch("6");
+
+        public static readonly DerObjectIdentifier kyber512 = new DerObjectIdentifier("1.3.6.1.4.1.2.267.8.2.2"); // pqc_kem_kyber.Branch("1");
+        public static readonly DerObjectIdentifier kyber768 = new DerObjectIdentifier("1.3.6.1.4.1.2.267.8.3.3"); // pqc_kem_kyber.Branch("2");
+        public static readonly DerObjectIdentifier kyber1024 = new DerObjectIdentifier("1.3.6.1.4.1.2.267.8.4.4"); // pqc_kem_kyber.Branch("3");
+        public static readonly DerObjectIdentifier kyber512_aes = new DerObjectIdentifier("1.3.6.1.4.1.2.267.10.2.2"); // pqc_kem_kyber.Branch("4");
+        public static readonly DerObjectIdentifier kyber768_aes = new DerObjectIdentifier("1.3.6.1.4.1.2.267.10.3.3"); // pqc_kem_kyber.Branch("5");
+        public static readonly DerObjectIdentifier kyber1024_aes = new DerObjectIdentifier("1.3.6.1.4.1.2.267.10.4.4"); // pqc_kem_kyber.Branch("6");
 	}
 }
diff --git a/crypto/src/pqc/crypto/crystals/dilithium/DilithiumPrivateKeyParameters.cs b/crypto/src/pqc/crypto/crystals/dilithium/DilithiumPrivateKeyParameters.cs
index ced1932bb..bb1b95ff6 100644
--- a/crypto/src/pqc/crypto/crystals/dilithium/DilithiumPrivateKeyParameters.cs
+++ b/crypto/src/pqc/crypto/crystals/dilithium/DilithiumPrivateKeyParameters.cs
@@ -26,40 +26,20 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Dilithium
             this.t1 = Arrays.Clone(t1);
         }
         
-        public byte[] GetRho()
-        {
-            return Arrays.Clone(rho);
-        }
+        public byte[] Rho => Arrays.Clone(rho);
 
-        public byte[] GetK()
-        {
-            return Arrays.Clone(k);
-        }
+        public byte[] K => Arrays.Clone(k);
 
-        public byte[] GetTr()
-        {
-            return Arrays.Clone(tr);
-        }
+        public byte[] Tr => Arrays.Clone(tr);
 
-        public byte[] GetS1()
-        {
-            return Arrays.Clone(s1);
-        }
+        public byte[] S1 => Arrays.Clone(s1);
 
-        public byte[] GetS2()
-        {
-            return Arrays.Clone(s2);
-        }
+        public byte[] S2 => Arrays.Clone(s2);
+        
 
-        public byte[] GetT0()
-        {
-            return Arrays.Clone(t0);
-        }
+        public byte[] T0 => Arrays.Clone(t0);
 
-        public byte[] GetT1()
-        {
-            return t1;
-        }
+        public byte[] T1 => t1;
 
         public byte[] GetEncoded()
         {
diff --git a/crypto/src/pqc/crypto/crystals/dilithium/DilithiumPublicKeyParameters.cs b/crypto/src/pqc/crypto/crystals/dilithium/DilithiumPublicKeyParameters.cs
index 138fb4983..506b919b7 100644
--- a/crypto/src/pqc/crypto/crystals/dilithium/DilithiumPublicKeyParameters.cs
+++ b/crypto/src/pqc/crypto/crystals/dilithium/DilithiumPublicKeyParameters.cs
@@ -26,14 +26,9 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Dilithium
         {
             return Arrays.Concatenate(rho, t1);
         }
-        public byte[] GetRho()
-        {
-            return Arrays.Clone(rho);
-        }
-        public byte[] GetT1()
-        {
-            return Arrays.Clone(t1);
-        }
+        public byte[] Rho => Arrays.Clone(rho);
+
+        public byte[] T1 => Arrays.Clone(t1);
 
     }
 }
\ No newline at end of file
diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberPrivateKeyParameters.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberPrivateKeyParameters.cs
index ab355be54..c9cf3a360 100644
--- a/crypto/src/pqc/crypto/crystals/kyber/KyberPrivateKeyParameters.cs
+++ b/crypto/src/pqc/crypto/crystals/kyber/KyberPrivateKeyParameters.cs
@@ -25,5 +25,12 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber
         {
             return Arrays.ConcatenateAll(m_s, m_t, m_rho, m_hpk, m_nonce);
         }
+
+        internal byte[] S => m_s;
+        internal byte[] Hpk => m_hpk;
+        internal byte[] Nonce => m_nonce;
+        internal byte[] T => m_t;
+        internal byte[] Rho => m_rho;
+
     }
 }
\ No newline at end of file
diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberPublicKeyParameters.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberPublicKeyParameters.cs
index 56d80f535..efc582abc 100644
--- a/crypto/src/pqc/crypto/crystals/kyber/KyberPublicKeyParameters.cs
+++ b/crypto/src/pqc/crypto/crystals/kyber/KyberPublicKeyParameters.cs
@@ -26,6 +26,9 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber
             m_t = Arrays.Clone(t);
             m_rho = Arrays.Clone(rho);
         }
+
+        internal byte[] T => m_t;
+        internal byte[] Rho => m_rho;
     }
 }
     
\ No newline at end of file
diff --git a/crypto/src/pqc/crypto/falcon/FalconKeyPairGenerator.cs b/crypto/src/pqc/crypto/falcon/FalconKeyPairGenerator.cs
index d7e4e5539..eafd1a9eb 100644
--- a/crypto/src/pqc/crypto/falcon/FalconKeyPairGenerator.cs
+++ b/crypto/src/pqc/crypto/falcon/FalconKeyPairGenerator.cs
@@ -13,7 +13,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Falcon
         private uint noncelen;
 
         private int pk_size;
-        private int sk_size;
 
         public void Init(KeyGenerationParameters param)
         {
@@ -36,18 +35,16 @@ namespace Org.BouncyCastle.Pqc.Crypto.Falcon
             {
                 sk_coeff_size = 7;
             }
+
             this.pk_size = 1 + (14 * n / 8);
-            this.sk_size = 1 + (2 * sk_coeff_size * n / 8) + (n);
         }
 
         public AsymmetricCipherKeyPair GenerateKeyPair()
         {
-            byte[] pk, sk;
-            pk = new byte[pk_size];
-            sk = new byte[sk_size];
-            nist.crypto_sign_keypair(pk, 0, sk, 0);
+            byte[] pk, sk, f, g, F;
+            nist.crypto_sign_keypair(out pk, out f, out g, out F);
             FalconParameters p = ((FalconKeyGenerationParameters)this.parameters).Parameters;
-            FalconPrivateKeyParameters privk = new FalconPrivateKeyParameters(p, sk);
+            FalconPrivateKeyParameters privk = new FalconPrivateKeyParameters(p, f, g, F, pk);
             FalconPublicKeyParameters pubk = new FalconPublicKeyParameters(p, pk);
             return new AsymmetricCipherKeyPair(pubk, privk);
         }
diff --git a/crypto/src/pqc/crypto/falcon/FalconNIST.cs b/crypto/src/pqc/crypto/falcon/FalconNIST.cs
index 50459532f..cce790734 100644
--- a/crypto/src/pqc/crypto/falcon/FalconNIST.cs
+++ b/crypto/src/pqc/crypto/falcon/FalconNIST.cs
@@ -57,13 +57,13 @@ namespace Org.BouncyCastle.Pqc.Crypto.Falcon
             }
         }
 
-        internal int crypto_sign_keypair(byte[] pksrc, int pk, byte[] sksrc, int sk)
+        internal int crypto_sign_keypair(out byte[] pk, out byte[] fEnc, out byte[] gEnc, out byte[] FEnc)
         {
+            byte[] sk = new byte[CRYPTO_SECRETKEYBYTES];
+            pk = new byte[CRYPTO_PUBLICKEYBYTES];
             int n = (int)1 << (int)this.logn;
             SHAKE256 rng = new SHAKE256();
-            sbyte[] f = new sbyte[n],
-                    g = new sbyte[n],
-                    F = new sbyte[n];
+            sbyte[] f = new sbyte[n], g = new sbyte[n], F = new sbyte[n];
             ushort[] h = new ushort[n];
             byte[] seed = new byte[48];
             int u, v;
@@ -81,26 +81,29 @@ namespace Org.BouncyCastle.Pqc.Crypto.Falcon
             /*
             * Encode private key.
             */
-            sksrc[sk+0] = (byte)(0x50 + this.logn);
+            sk[0] = (byte)(0x50 + this.logn);
             u = 1;
-            v = this.codec.trim_i8_encode(sksrc, sk + u, CRYPTO_SECRETKEYBYTES - u,
+            v = this.codec.trim_i8_encode(sk, u, CRYPTO_SECRETKEYBYTES - u,
                 f, 0, this.logn, this.codec.max_fg_bits[this.logn]);
             if (v == 0) {
                 // TODO check which exception types to use here
                 throw new InvalidOperationException("f encode failed");
             }
+            fEnc = Arrays.CopyOfRange(sk, u, u + v);
             u += v;
-            v = this.codec.trim_i8_encode(sksrc, sk + u, CRYPTO_SECRETKEYBYTES - u,
+            v = this.codec.trim_i8_encode(sk, u, CRYPTO_SECRETKEYBYTES - u,
                 g, 0, this.logn, this.codec.max_fg_bits[this.logn]);
             if (v == 0) {
                 throw new InvalidOperationException("g encode failed");
             }
+            gEnc = Arrays.CopyOfRange(sk, u, u + v);
             u += v;
-            v = this.codec.trim_i8_encode(sksrc, sk + u, CRYPTO_SECRETKEYBYTES - u,
+            v = this.codec.trim_i8_encode(sk,  u, CRYPTO_SECRETKEYBYTES - u,
                 F, 0, this.logn, this.codec.max_FG_bits[this.logn]);
             if (v == 0) {
                  throw new InvalidOperationException("F encode failed");
             }
+            FEnc = Arrays.CopyOfRange(sk, u, u + v);
             u += v;
             if (u != CRYPTO_SECRETKEYBYTES) {
                  throw new InvalidOperationException("secret key encoding failed");
@@ -109,12 +112,14 @@ namespace Org.BouncyCastle.Pqc.Crypto.Falcon
             /*
             * Encode public key.
             */
-            pksrc[pk+0] = (byte)(0x00 + this.logn);
-            v = this.codec.modq_encode(pksrc, pk + 1, CRYPTO_PUBLICKEYBYTES - 1, h, 0, this.logn);
+            pk[0] = (byte)(0x00 + this.logn);
+            v = this.codec.modq_encode(pk, 1, CRYPTO_PUBLICKEYBYTES - 1, h, 0, this.logn);
             if (v != CRYPTO_PUBLICKEYBYTES - 1) {
                  throw new InvalidOperationException("public key encoding failed");
             }
 
+            pk = Arrays.CopyOfRange(pk, 1, pk.Length);
+
             return 0;
         }
 
@@ -133,43 +138,51 @@ namespace Org.BouncyCastle.Pqc.Crypto.Falcon
                     g = new sbyte[n],
                     F = new sbyte[n],
                     G = new sbyte[n];
+            
             short[] sig = new short[n];
             ushort[] hm = new ushort[n];
+            
             byte[] seed = new byte[48],
                     nonce = new byte[this.noncelen];
+            
             byte[] esig = new byte[this.CRYPTO_BYTES - 2 - this.noncelen];
             SHAKE256 sc = new SHAKE256();
             FalconSign signer = new FalconSign(this.common);
 
-            /*
-            * Decode the private key.
-            */
-            if (sksrc[sk+0] != 0x50 + this.logn) {
-                throw new ArgumentException("private key header incorrect");
-            }
-            u = 1;
+            // /*
+            // * Decode the private key.
+            // */
+            // if (sksrc[sk+0] != 0x50 + this.logn) {
+            //     throw new ArgumentException("private key header incorrect");
+            // }
+            u = 0;
             v = this.codec.trim_i8_decode(f, 0, this.logn, this.codec.max_fg_bits[this.logn],
                 sksrc, sk + u, CRYPTO_SECRETKEYBYTES - u);
-            if (v == 0) {
+            if (v == 0)
+            {
                 throw new InvalidOperationException("f decode failed");
             }
             u += v;
             v = this.codec.trim_i8_decode(g, 0, this.logn, this.codec.max_fg_bits[this.logn],
                 sksrc, sk + u, CRYPTO_SECRETKEYBYTES - u);
-            if (v == 0) {
+            if (v == 0)
+            {
                 throw new InvalidOperationException("g decode failed");
             }
             u += v;
             v = this.codec.trim_i8_decode(F, 0, this.logn, this.codec.max_FG_bits[this.logn],
                 sksrc, sk + u, CRYPTO_SECRETKEYBYTES - u);
-            if (v == 0) {
+            if (v == 0) 
+            {
                 throw new InvalidOperationException("F decode failed");
             }
             u += v;
-            if (u != CRYPTO_SECRETKEYBYTES) {
+            if (u != CRYPTO_SECRETKEYBYTES - 1) 
+            {
                 throw new InvalidOperationException("full Key not used");
             }
-            if (this.vrfy.complete_private(G, 0, f, 0, g, 0, F, 0, this.logn, new ushort[2 * n],0) == 0) {
+            if (this.vrfy.complete_private(G, 0, f, 0, g, 0, F, 0, this.logn, new ushort[2 * n],0) == 0) 
+            {
                 throw new InvalidOperationException("complete private failed");
             }
 
@@ -238,10 +251,10 @@ namespace Org.BouncyCastle.Pqc.Crypto.Falcon
             /*
             * Decode public key.
             */
-            if (pksrc[pk+0] != 0x00 + this.logn) {
-                return -1;
-            }
-            if (this.codec.modq_decode(h, 0, this.logn, pksrc, pk + 1, CRYPTO_PUBLICKEYBYTES - 1)
+            // if (pksrc[pk+0] != 0x00 + this.logn) {
+            //     return -1;
+            // }
+            if (this.codec.modq_decode(h, 0, this.logn, pksrc, pk, CRYPTO_PUBLICKEYBYTES - 1)
                 != CRYPTO_PUBLICKEYBYTES - 1)
             {
                 return -1;
diff --git a/crypto/src/pqc/crypto/falcon/FalconPrivateKeyParameters.cs b/crypto/src/pqc/crypto/falcon/FalconPrivateKeyParameters.cs
index d30aafcf4..c912a222c 100644
--- a/crypto/src/pqc/crypto/falcon/FalconPrivateKeyParameters.cs
+++ b/crypto/src/pqc/crypto/falcon/FalconPrivateKeyParameters.cs
@@ -6,17 +6,43 @@ namespace Org.BouncyCastle.Pqc.Crypto.Falcon
     public class FalconPrivateKeyParameters
         : FalconKeyParameters
     {
-        private byte[] privateKey;
+        private byte[] pk;
+        private byte[] f;
+        private byte[] g;
+        private byte[] F;
 
-        public FalconPrivateKeyParameters(FalconParameters parameters, byte[] sk_encoded)
+        public FalconPrivateKeyParameters(FalconParameters parameters, byte[] f, byte[] g, byte[] F, byte[] pk_encoded)
             : base(true, parameters)
         {
-            this.privateKey = Arrays.Clone(sk_encoded);
+            this.f = Arrays.Clone(f);
+            this.g = Arrays.Clone(g);
+            this.F = Arrays.Clone(F);
+            this.pk = Arrays.Clone(pk_encoded);
         }
 
         public byte[] GetEncoded()
         {
-            return Arrays.Clone(privateKey);
+            return Arrays.ConcatenateAll(f, g, F);
+        }
+        
+        public byte[] GetPublicKey()
+        {
+            return Arrays.Clone(pk);
+        }
+
+        public byte[] GetSpolyf()
+        {
+            return Arrays.Clone(f);
+        }
+
+        public byte[] GetG()
+        {
+            return Arrays.Clone(g);
+        }
+
+        public byte[] GetSpolyF()
+        {
+            return Arrays.Clone(F);
         }
     }
 }
diff --git a/crypto/src/pqc/crypto/utils/PqcUtilities.cs b/crypto/src/pqc/crypto/utils/PqcUtilities.cs
index a1fb04340..f0603ed16 100644
--- a/crypto/src/pqc/crypto/utils/PqcUtilities.cs
+++ b/crypto/src/pqc/crypto/utils/PqcUtilities.cs
@@ -4,6 +4,9 @@ using System.Collections.Generic;
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.BC;
 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.Picnic;
 using Org.BouncyCastle.Pqc.Crypto.Saber;
 using Org.BouncyCastle.Pqc.Crypto.Sike;
@@ -24,6 +27,15 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
         
         private readonly static Dictionary<SIKEParameters, DerObjectIdentifier> sikeOids = new Dictionary<SIKEParameters, DerObjectIdentifier>();
         private readonly static Dictionary<DerObjectIdentifier, SIKEParameters> sikeParams = new Dictionary<DerObjectIdentifier, SIKEParameters>();
+     
+        private readonly static Dictionary<KyberParameters, DerObjectIdentifier> kyberOids = new Dictionary<KyberParameters, DerObjectIdentifier>();
+        private readonly static Dictionary<DerObjectIdentifier, KyberParameters> kyberParams = new Dictionary<DerObjectIdentifier, KyberParameters>();
+
+        private readonly static Dictionary<DilithiumParameters, DerObjectIdentifier> dilithiumOids = new Dictionary<DilithiumParameters, DerObjectIdentifier>();
+        private readonly static Dictionary<DerObjectIdentifier, DilithiumParameters> dilithiumParams = new Dictionary<DerObjectIdentifier, DilithiumParameters>();
+
+        private readonly static Dictionary<FalconParameters, DerObjectIdentifier> falconOids = new Dictionary<FalconParameters, DerObjectIdentifier>();
+        private readonly static Dictionary<DerObjectIdentifier, FalconParameters> falconParams = new Dictionary<DerObjectIdentifier, FalconParameters>();
 
         
         static PqcUtilities()
@@ -108,13 +120,46 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
             sikeParams[BCObjectIdentifiers.sikep751_compressed] = SIKEParameters.sikep751_compressed;
             
             sikeOids[SIKEParameters.sikep434] = BCObjectIdentifiers.sikep434;
-            sikeOids[SIKEParameters.sikep503] = BCObjectIdentifiers.sikep503;
-            sikeOids[SIKEParameters.sikep610] = BCObjectIdentifiers.sikep610;
-            sikeOids[SIKEParameters.sikep751] = BCObjectIdentifiers.sikep751;
-            sikeOids[SIKEParameters.sikep434_compressed] = BCObjectIdentifiers.sikep434_compressed;
-            sikeOids[SIKEParameters.sikep503_compressed] = BCObjectIdentifiers.sikep503_compressed;
-            sikeOids[SIKEParameters.sikep610_compressed] = BCObjectIdentifiers.sikep610_compressed;
-            sikeOids[SIKEParameters.sikep751_compressed] = BCObjectIdentifiers.sikep751_compressed;
+            sikeOids[SIKEParameters.sikep434] = BCObjectIdentifiers.sikep434;
+            sikeOids[SIKEParameters.sikep434] = BCObjectIdentifiers.sikep434;
+            sikeOids[SIKEParameters.sikep434] = BCObjectIdentifiers.sikep434;
+            sikeOids[SIKEParameters.sikep434] = BCObjectIdentifiers.sikep434;
+            sikeOids[SIKEParameters.sikep434] = BCObjectIdentifiers.sikep434;
+            
+            kyberOids[KyberParameters.kyber512] = BCObjectIdentifiers.kyber512;
+            kyberOids[KyberParameters.kyber768] = BCObjectIdentifiers.kyber768;
+            kyberOids[KyberParameters.kyber1024] = BCObjectIdentifiers.kyber1024;
+            kyberOids[KyberParameters.kyber512_aes] = BCObjectIdentifiers.kyber512_aes;
+            kyberOids[KyberParameters.kyber768_aes] = BCObjectIdentifiers.kyber768_aes;
+            kyberOids[KyberParameters.kyber1024_aes] = BCObjectIdentifiers.kyber1024_aes;   
+            
+            kyberParams[BCObjectIdentifiers.kyber512] = KyberParameters.kyber512;
+            kyberParams[BCObjectIdentifiers.kyber768] = KyberParameters.kyber768;
+            kyberParams[BCObjectIdentifiers.kyber1024] = KyberParameters.kyber1024;
+            kyberParams[BCObjectIdentifiers.kyber512_aes] = KyberParameters.kyber512_aes;
+            kyberParams[BCObjectIdentifiers.kyber768_aes] = KyberParameters.kyber768_aes;
+            kyberParams[BCObjectIdentifiers.kyber1024_aes] = KyberParameters.kyber1024_aes;
+            
+            
+            falconOids[FalconParameters.falcon_512] = BCObjectIdentifiers.falcon_512;
+            falconOids[FalconParameters.falcon_1024] = BCObjectIdentifiers.falcon_1024;
+            
+            falconParams[BCObjectIdentifiers.falcon_512] = FalconParameters.falcon_512;
+            falconParams[BCObjectIdentifiers.falcon_1024] = FalconParameters.falcon_1024;
+            
+            dilithiumOids[DilithiumParameters.Dilithium2] = BCObjectIdentifiers.dilithium2;
+            dilithiumOids[DilithiumParameters.Dilithium3] = BCObjectIdentifiers.dilithium3;
+            dilithiumOids[DilithiumParameters.Dilithium5] = BCObjectIdentifiers.dilithium5;
+            dilithiumOids[DilithiumParameters.Dilithium2Aes] = BCObjectIdentifiers.dilithium2_aes;
+            dilithiumOids[DilithiumParameters.Dilithium3Aes] = BCObjectIdentifiers.dilithium3_aes;
+            dilithiumOids[DilithiumParameters.Dilithium5Aes] = BCObjectIdentifiers.dilithium5_aes;
+            
+            dilithiumParams[BCObjectIdentifiers.dilithium2] = DilithiumParameters.Dilithium2;
+            dilithiumParams[BCObjectIdentifiers.dilithium3] = DilithiumParameters.Dilithium3;
+            dilithiumParams[BCObjectIdentifiers.dilithium5] = DilithiumParameters.Dilithium5;
+            dilithiumParams[BCObjectIdentifiers.dilithium2_aes] = DilithiumParameters.Dilithium2Aes;
+            dilithiumParams[BCObjectIdentifiers.dilithium3_aes] = DilithiumParameters.Dilithium3Aes;
+            dilithiumParams[BCObjectIdentifiers.dilithium5_aes] = DilithiumParameters.Dilithium5Aes;
         }
 
         public static DerObjectIdentifier McElieceOidLookup(CmceParameters parameters)
@@ -135,6 +180,30 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
         {
             return saberParams[oid];
         }
+        internal static KyberParameters KyberParamsLookup(DerObjectIdentifier oid)
+        {
+            return kyberParams[oid];
+        }       
+        internal static DerObjectIdentifier KyberOidLookup(KyberParameters parameters)
+        {
+            return kyberOids[parameters];
+        }
+        internal static FalconParameters FalconParamsLookup(DerObjectIdentifier oid)
+        {
+            return falconParams[oid];
+        }       
+        internal static DerObjectIdentifier FalconOidLookup(FalconParameters parameters)
+        {
+            return falconOids[parameters];
+        }
+        internal static DilithiumParameters DilithiumParamsLookup(DerObjectIdentifier oid)
+        {
+            return dilithiumParams[oid];
+        }       
+        internal static DerObjectIdentifier DilithiumOidLookup(DilithiumParameters parameters)
+        {
+            return dilithiumOids[parameters];
+        }
 
         internal static DerObjectIdentifier SphincsPlusOidLookup(SPHINCSPlusParameters parameters)
         {
diff --git a/crypto/src/pqc/crypto/utils/PrivateKeyFactory.cs b/crypto/src/pqc/crypto/utils/PrivateKeyFactory.cs
index 0fadab855..db424faac 100644
--- a/crypto/src/pqc/crypto/utils/PrivateKeyFactory.cs
+++ b/crypto/src/pqc/crypto/utils/PrivateKeyFactory.cs
@@ -10,6 +10,9 @@ using Org.BouncyCastle.Crypto.Utilities;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Pqc.Asn1;
 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.Lms;
 using Org.BouncyCastle.Pqc.Crypto.Picnic;
 using Org.BouncyCastle.Pqc.Crypto.Saber;
@@ -105,6 +108,114 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
 
                 return new SIKEPrivateKeyParameters(sikeParams, keyEnc);
             }
+            if (algOID.Equals(BCObjectIdentifiers.kyber512)
+                || algOID.Equals(BCObjectIdentifiers.kyber512_aes)
+                || algOID.Equals(BCObjectIdentifiers.kyber768)
+                || algOID.Equals(BCObjectIdentifiers.kyber768_aes)
+                || algOID.Equals(BCObjectIdentifiers.kyber1024)
+                || algOID.Equals(BCObjectIdentifiers.kyber1024_aes))
+            {
+                Asn1Sequence keyEnc = Asn1Sequence.GetInstance(keyInfo.ParsePrivateKey());
+
+                KyberParameters spParams = PqcUtilities.KyberParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm);
+
+                int version = DerInteger.GetInstance(keyEnc[0]).Value.IntValue;
+                if (version != 0)
+                {
+                    throw new IOException("unknown private key version: " + version);
+                }
+ 
+                if (keyInfo.PublicKeyData != null)
+                {
+                    Asn1Sequence pubKey = Asn1Sequence.GetInstance(keyInfo.PublicKeyData.GetOctets());
+                    return new KyberPrivateKeyParameters(spParams,
+                        Asn1OctetString.GetInstance(keyEnc[1]).GetDerEncoded(), 
+                        Asn1OctetString.GetInstance(keyEnc[2]).GetOctets(), 
+                        Asn1OctetString.GetInstance(keyEnc[3]).GetOctets(),
+                        Asn1OctetString.GetInstance(pubKey[0]).GetOctets(), // t
+                        Asn1OctetString.GetInstance(pubKey[1]).GetOctets()); // rho
+                }
+                else
+                {
+                    return new KyberPrivateKeyParameters(spParams,
+                        Asn1OctetString.GetInstance(keyEnc[1]).GetOctets(),
+                        Asn1OctetString.GetInstance(keyEnc[2]).GetOctets(),
+                        Asn1OctetString.GetInstance(keyEnc[3]).GetOctets(),
+                        null,
+                        null);
+                }
+            }
+            if (algOID.Equals(BCObjectIdentifiers.dilithium2)
+                || algOID.Equals(BCObjectIdentifiers.dilithium3)
+                || algOID.Equals(BCObjectIdentifiers.dilithium5)
+                || algOID.Equals(BCObjectIdentifiers.dilithium2_aes)
+                || algOID.Equals(BCObjectIdentifiers.dilithium3_aes)
+                || algOID.Equals(BCObjectIdentifiers.dilithium5_aes))
+            {
+                Asn1Sequence keyEnc = Asn1Sequence.GetInstance(keyInfo.ParsePrivateKey());
+
+                DilithiumParameters spParams = PqcUtilities.DilithiumParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm);
+
+                int version = DerInteger.GetInstance(keyEnc[0]).Value.IntValue;
+                if (version != 0)
+                {
+                    throw new IOException("unknown private key version: " + version);
+                }
+
+                if (keyInfo.PublicKeyData != null)
+                {
+                    Asn1Sequence pubKey = Asn1Sequence.GetInstance(keyInfo.PublicKeyData.GetOctets());
+                    return new DilithiumPrivateKeyParameters(spParams,
+                        DerBitString.GetInstance(keyEnc[1]).GetOctets(),
+                        DerBitString.GetInstance(keyEnc[2]).GetOctets(),
+                        DerBitString.GetInstance(keyEnc[3]).GetOctets(),
+                        DerBitString.GetInstance(keyEnc[4]).GetOctets(),
+                        DerBitString.GetInstance(keyEnc[5]).GetOctets(),
+                        DerBitString.GetInstance(keyEnc[6]).GetOctets(),
+                        Asn1OctetString.GetInstance(pubKey[1]).GetOctets()); // encT1
+                }
+                else
+                {
+                    return new DilithiumPrivateKeyParameters(spParams,
+                        DerBitString.GetInstance(keyEnc[1]).GetOctets(),
+                        DerBitString.GetInstance(keyEnc[2]).GetOctets(),
+                        DerBitString.GetInstance(keyEnc[3]).GetOctets(),
+                        DerBitString.GetInstance(keyEnc[4]).GetOctets(),
+                        DerBitString.GetInstance(keyEnc[5]).GetOctets(),
+                        DerBitString.GetInstance(keyEnc[6]).GetOctets(),
+                        null);
+                }
+            }
+            if (algOID.Equals(BCObjectIdentifiers.falcon_512) || algOID.Equals(BCObjectIdentifiers.falcon_1024))
+                {
+                    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);
+                    }
+
+                    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);
+                    }
+                }
             
             
             throw new Exception("algorithm identifier in private key not recognised");
diff --git a/crypto/src/pqc/crypto/utils/PrivateKeyInfoFactory.cs b/crypto/src/pqc/crypto/utils/PrivateKeyInfoFactory.cs
index c5c3f9e45..42bc3ca91 100644
--- a/crypto/src/pqc/crypto/utils/PrivateKeyInfoFactory.cs
+++ b/crypto/src/pqc/crypto/utils/PrivateKeyInfoFactory.cs
@@ -6,6 +6,9 @@ using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Pqc.Asn1;
 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.Lms;
 using Org.BouncyCastle.Pqc.Crypto.Picnic;
 using Org.BouncyCastle.Pqc.Crypto.Saber;
@@ -109,6 +112,62 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
                 AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.SikeOidLookup(parameters.GetParameters()));
                 return new PrivateKeyInfo(algorithmIdentifier, new DerOctetString(encoding), attributes);
             }
+            if (privateKey is 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()));
+
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.FalconOidLookup(parameters.Parameters));
+
+                return new PrivateKeyInfo(algorithmIdentifier, new DerSequence(v), attributes, parameters.GetPublicKey());
+            }
+            if (privateKey is 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));
+
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.KyberOidLookup(parameters.Parameters));
+
+                Asn1EncodableVector vPub = new Asn1EncodableVector();
+                vPub.Add(new DerOctetString(parameters.T));
+                vPub.Add(new DerOctetString(parameters.Rho));
+
+                return new PrivateKeyInfo(algorithmIdentifier, new DerSequence(v), attributes, new DerSequence(vPub).GetEncoded());
+            }
+            if (privateKey is 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));
+
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.DilithiumOidLookup(parameters.Parameters));
+
+                Asn1EncodableVector vPub = new Asn1EncodableVector();
+                vPub.Add(new DerOctetString(parameters.Rho));
+                vPub.Add(new DerOctetString(parameters.T1));
+
+                return new PrivateKeyInfo(algorithmIdentifier, new DerSequence(v), attributes, new DerSequence(vPub).GetEncoded());
+            }
 
             throw new ArgumentException("Class provided is not convertible: " + Platform.GetTypeName(privateKey));
         }
diff --git a/crypto/src/pqc/crypto/utils/PublicKeyFactory.cs b/crypto/src/pqc/crypto/utils/PublicKeyFactory.cs
index 3610711ff..e2279c15c 100644
--- a/crypto/src/pqc/crypto/utils/PublicKeyFactory.cs
+++ b/crypto/src/pqc/crypto/utils/PublicKeyFactory.cs
@@ -10,6 +10,9 @@ using Org.BouncyCastle.Crypto.Utilities;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Pqc.Asn1;
 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.Picnic;
 using Org.BouncyCastle.Pqc.Crypto.Saber;
 using Org.BouncyCastle.Pqc.Crypto.Sike;
@@ -73,6 +76,23 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
             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.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();
         }
         
         /// <summary> Create a public key from a SubjectPublicKeyInfo encoding</summary>
@@ -190,5 +210,82 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
                 return new SIKEPublicKeyParameters(sikeParams, keyEnc);
             }
         }
+        private class DilithiumConverter
+            : SubjectPublicKeyInfoConverter
+        {
+            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+            {
+                DilithiumParameters dilithiumParams = PqcUtilities.DilithiumParamsLookup(keyInfo.AlgorithmID.Algorithm);
+
+                Asn1Object obj = keyInfo.ParsePublicKey();
+                if (obj is Asn1Sequence)
+                {
+                    Asn1Sequence keySeq = Asn1Sequence.GetInstance(obj);
+
+                    return new DilithiumPublicKeyParameters(dilithiumParams,
+                        Asn1OctetString.GetInstance(keySeq[0]).GetOctets(),
+                        Asn1OctetString.GetInstance(keySeq[1]).GetOctets());
+                }
+                else
+                {
+                    byte[] encKey = Asn1OctetString.GetInstance(obj).GetOctets();
+
+                    return new DilithiumPublicKeyParameters(dilithiumParams, encKey);
+                }
+            }
+        }
+
+        private class KyberConverter
+            : SubjectPublicKeyInfoConverter
+        {
+            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+            {
+                KyberParameters kyberParameters = PqcUtilities.KyberParamsLookup(keyInfo.AlgorithmID.Algorithm);
+
+                Asn1Object obj = keyInfo.ParsePublicKey();
+                if (obj is Asn1Sequence)
+                {
+                    Asn1Sequence keySeq = Asn1Sequence.GetInstance(obj);
+
+                    return new KyberPublicKeyParameters(kyberParameters,
+                        Asn1OctetString.GetInstance(keySeq[0]).GetOctets(),
+                        Asn1OctetString.GetInstance(keySeq[1]).GetOctets());
+                }
+                else
+                {
+                    byte[] encKey = Asn1OctetString.GetInstance(obj).GetOctets();
+
+                    return new KyberPublicKeyParameters(kyberParameters, encKey);
+                }
+            }
+        }
+        
+        private class FalconConverter 
+            : SubjectPublicKeyInfoConverter
+        {
+            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+            {
+                FalconParameters falconParams = PqcUtilities.FalconParamsLookup(keyInfo.AlgorithmID.Algorithm);
+
+                Asn1Object obj = keyInfo.ParsePublicKey();
+                if (obj is Asn1Sequence)
+                {
+                    byte[] keyEnc = Asn1OctetString.GetInstance(Asn1Sequence.GetInstance(obj)[0]).GetOctets();
+
+                    return new FalconPublicKeyParameters(falconParams, keyEnc);
+                }
+                else
+                {
+                    // header byte + h
+                    byte[] keyEnc = Asn1OctetString.GetInstance(obj).GetOctets();
+
+                    if (keyEnc[0] != (byte)(0x00 + falconParams.LogN))
+                    {
+                        throw new ArgumentException("byte[] enc of Falcon h value not tagged correctly");
+                    }
+                    return new FalconPublicKeyParameters(falconParams, Arrays.CopyOfRange(keyEnc, 1, keyEnc.Length));
+                }
+            }
+        }
     }
 }
\ 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 0cf80bbe3..eea6b8717 100644
--- a/crypto/src/pqc/crypto/utils/SubjectPublicKeyInfoFactory.cs
+++ b/crypto/src/pqc/crypto/utils/SubjectPublicKeyInfoFactory.cs
@@ -6,6 +6,9 @@ using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Pqc.Asn1;
 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.Picnic;
 using Org.BouncyCastle.Pqc.Crypto.Saber;
 using Org.BouncyCastle.Pqc.Crypto.Sike;
@@ -87,6 +90,35 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
                 AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.SikeOidLookup(parameters.GetParameters()));
                 return new SubjectPublicKeyInfo(algorithmIdentifier, new DerOctetString(encoding));
             }
+            if (publicKey is FalconPublicKeyParameters)
+            {
+                FalconPublicKeyParameters parameters = (FalconPublicKeyParameters)publicKey;
+
+                byte[] encoding = parameters.GetEncoded();
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.FalconOidLookup(parameters.Parameters));
+
+                return new SubjectPublicKeyInfo(algorithmIdentifier, new DerSequence(new DerOctetString(encoding)));
+            }
+            if (publicKey is KyberPublicKeyParameters)
+            {
+                KyberPublicKeyParameters parameters = (KyberPublicKeyParameters)publicKey;
+
+                AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PqcUtilities.KyberOidLookup(parameters.Parameters));
+                Asn1EncodableVector v = new Asn1EncodableVector();
+                v.Add(new DerOctetString(parameters.T));
+                v.Add(new DerOctetString(parameters.Rho));
+                return new SubjectPublicKeyInfo(algorithmIdentifier, new DerSequence(v));
+            }
+            if (publicKey is 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));
+            }
             
             throw new ArgumentException("Class provided no convertible: " + Platform.GetTypeName(publicKey));
 
diff --git a/crypto/test/src/pqc/crypto/test/FalconTest.cs b/crypto/test/src/pqc/crypto/test/FalconTest.cs
index bcda32669..4ede0803d 100644
--- a/crypto/test/src/pqc/crypto/test/FalconTest.cs
+++ b/crypto/test/src/pqc/crypto/test/FalconTest.cs
@@ -63,11 +63,14 @@ namespace Org.BouncyCastle.Pqc.Crypto.Tests
                             AsymmetricCipherKeyPair ackp = kpg.GenerateKeyPair();
                             byte[] respk = ((FalconPublicKeyParameters) ackp.Public).GetEncoded();
                             byte[] ressk = ((FalconPrivateKeyParameters) ackp.Private).GetEncoded();
+                            
+                            //keygen
+                            Assert.True(Arrays.AreEqual(respk, 0, respk.Length, pk, 1, pk.Length), name + " " + count + " public key");
+                            Assert.True(Arrays.AreEqual(ressk, 0, ressk.Length, sk, 1, sk.Length), name + " " + count + " private key");
 
                             // sign
                             FalconSigner signer = new FalconSigner();
-                            FalconPrivateKeyParameters skparam = new FalconPrivateKeyParameters(parameters[fileIndex], sk);
-                            ParametersWithRandom skwrand = new ParametersWithRandom(skparam, random);
+                            ParametersWithRandom skwrand = new ParametersWithRandom(ackp.Private, random);
                             signer.Init(true, skwrand);
                             byte[] sig = signer.GenerateSignature(msg);
                             byte[] ressm = new byte[2 + msg.Length + sig.Length - 1];
@@ -79,7 +82,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Tests
 
                             // verify
                             FalconSigner verifier = new FalconSigner();
-                            FalconPublicKeyParameters pkparam = new FalconPublicKeyParameters(parameters[fileIndex], pk);
+                            FalconPublicKeyParameters pkparam = (FalconPublicKeyParameters)ackp.Public;
                             verifier.Init(false, pkparam);
                             byte[] noncesig = new byte[sm_len - m_len - 2 + 1];
                             noncesig[0] = (byte)(0x30 + parameters[fileIndex].LogN);
@@ -88,51 +91,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Tests
                             bool vrfyrespass = verifier.VerifySignature(msg, noncesig);
                             noncesig[42]++; // changing the signature by 1 byte should cause it to fail
                             bool vrfyresfail = verifier.VerifySignature(msg, noncesig);
-
-                            // print results
-                            /*
-                            System.out.println("--Keygen");
-                            bool kgenpass = true;
-                            if (!Arrays.areEqual(respk, pk)) {
-                                System.out.println("  == Keygen: pk do not match");
-                                kgenpass = false;
-                            }
-                            if (!Arrays.areEqual(ressk, sk)) {
-                                System.out.println("  == Keygen: sk do not match");
-                                kgenpass = false;
-                            }
-                            if (kgenpass) {
-                                System.out.println("  ++ Keygen pass");
-                            } else {
-                                System.out.println("  == Keygen failed");
-                                return;
-                            }
-
-                            System.out.println("--Sign");
-                            bool spass = true;
-                            if (!Arrays.areEqual(ressm, sm)) {
-                                System.out.println("  == Sign: signature do not match");
-                                spass = false;
-                            }
-                            if (spass) {
-                                System.out.println("  ++ Sign pass");
-                            } else {
-                                System.out.println("  == Sign failed");
-                                return;
-                            }
-
-                            System.out.println("--Verify");
-                            if (vrfyrespass && !vrfyresfail) {
-                                System.out.println("  ++ Verify pass");
-                            } else {
-                                System.out.println("  == Verify failed");
-                                return;
-                            }
-                            */
-                            // Assert.True
-                            //keygen
-                            Assert.True(Arrays.AreEqual(respk, pk), name + " " + count + " public key");
-                            Assert.True(Arrays.AreEqual(ressk, sk), name + " " + count + " private key");
+                            
                             //sign
                             Assert.True(Arrays.AreEqual(ressm, sm), name + " " + count + " signature");
                             //verify