summary refs log tree commit diff
path: root/crypto
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2023-05-02 20:55:51 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2023-05-02 20:55:51 +0700
commit4332f34f7a60dc07bdbf5ef894b3d529568a859a (patch)
treeda626963aa3b99b42621706d7f9676d78de12b0a /crypto
parentUpdate XMSS OIDs (diff)
downloadBouncyCastle.NET-ed25519-4332f34f7a60dc07bdbf5ef894b3d529568a859a.tar.xz
Update SphincsPlus from bc-java
- refactoring in Pqc
Diffstat (limited to 'crypto')
-rw-r--r--crypto/src/asn1/bc/BCObjectIdentifiers.cs40
-rw-r--r--crypto/src/pqc/asn1/CmcePrivateKey.cs5
-rw-r--r--crypto/src/pqc/asn1/CmcePublicKey.cs8
-rw-r--r--crypto/src/pqc/asn1/PqcObjectIdentifiers.cs103
-rw-r--r--crypto/src/pqc/asn1/SphincsPlusPrivateKey.cs96
-rw-r--r--crypto/src/pqc/asn1/SphincsPlusPublicKey.cs61
-rw-r--r--crypto/src/pqc/crypto/bike/BikeKemExtractor.cs6
-rw-r--r--crypto/src/pqc/crypto/bike/BikeKemGenerator.cs2
-rw-r--r--crypto/src/pqc/crypto/bike/BikePrivateKeyParameters.cs44
-rw-r--r--crypto/src/pqc/crypto/bike/BikePublicKeyParameters.cs16
-rw-r--r--crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusParameters.cs180
-rw-r--r--crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusPrivateKeyParameters.cs38
-rw-r--r--crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusPublicKeyParameters.cs10
-rw-r--r--crypto/src/pqc/crypto/utils/PqcPrivateKeyFactory.cs68
-rw-r--r--crypto/src/pqc/crypto/utils/PqcPrivateKeyInfoFactory.cs10
-rw-r--r--crypto/src/pqc/crypto/utils/PqcPublicKeyFactory.cs28
-rw-r--r--crypto/src/pqc/crypto/utils/PqcUtilities.cs64
-rw-r--r--crypto/test/src/pqc/crypto/test/SphincsPlusTest.cs9
18 files changed, 572 insertions, 216 deletions
diff --git a/crypto/src/asn1/bc/BCObjectIdentifiers.cs b/crypto/src/asn1/bc/BCObjectIdentifiers.cs
index 7f369cd91..eb7d8e058 100644
--- a/crypto/src/asn1/bc/BCObjectIdentifiers.cs
+++ b/crypto/src/asn1/bc/BCObjectIdentifiers.cs
@@ -119,13 +119,51 @@ namespace Org.BouncyCastle.Asn1.BC
         public static readonly DerObjectIdentifier xmss_mt_with_SHAKE256 = xmss_mt_SHAKE256ph;
 
         /**
+         * qTESLA
+         */
+        public static readonly DerObjectIdentifier qTESLA = bc_sig.Branch("4");
+
+        public static readonly DerObjectIdentifier qTESLA_Rnd1_I = qTESLA.Branch("1");
+        public static readonly DerObjectIdentifier qTESLA_Rnd1_III_size = qTESLA.Branch("2");
+        public static readonly DerObjectIdentifier qTESLA_Rnd1_III_speed = qTESLA.Branch("3");
+        public static readonly DerObjectIdentifier qTESLA_Rnd1_p_I = qTESLA.Branch("4");
+        public static readonly DerObjectIdentifier qTESLA_Rnd1_p_III = qTESLA.Branch("5");
+
+        public static readonly DerObjectIdentifier qTESLA_p_I = qTESLA.Branch("11");
+        public static readonly DerObjectIdentifier qTESLA_p_III = qTESLA.Branch("12");
+
+        /**
          * SPHINCS+
          */
         public static readonly DerObjectIdentifier sphincsPlus = bc_sig.Branch("5");
+        public static readonly DerObjectIdentifier sphincsPlus_sha2_128s_r3 = sphincsPlus.Branch("1");
+        public static readonly DerObjectIdentifier sphincsPlus_sha2_128f_r3 = sphincsPlus.Branch("2");
+        public static readonly DerObjectIdentifier sphincsPlus_shake_128s_r3 = sphincsPlus.Branch("3");
+        public static readonly DerObjectIdentifier sphincsPlus_shake_128f_r3 = sphincsPlus.Branch("4");
+        public static readonly DerObjectIdentifier sphincsPlus_haraka_128s_r3 = sphincsPlus.Branch("5");
+        public static readonly DerObjectIdentifier sphincsPlus_haraka_128f_r3 = sphincsPlus.Branch("6");
+
+        public static readonly DerObjectIdentifier sphincsPlus_sha2_192s_r3 = sphincsPlus.Branch("7");
+        public static readonly DerObjectIdentifier sphincsPlus_sha2_192f_r3 = sphincsPlus.Branch("8");
+        public static readonly DerObjectIdentifier sphincsPlus_shake_192s_r3 = sphincsPlus.Branch("9");
+        public static readonly DerObjectIdentifier sphincsPlus_shake_192f_r3 = sphincsPlus.Branch("10");
+        public static readonly DerObjectIdentifier sphincsPlus_haraka_192s_r3 = sphincsPlus.Branch("11");
+        public static readonly DerObjectIdentifier sphincsPlus_haraka_192f_r3 = sphincsPlus.Branch("12");
+
+        public static readonly DerObjectIdentifier sphincsPlus_sha2_256s_r3 = sphincsPlus.Branch("13");
+        public static readonly DerObjectIdentifier sphincsPlus_sha2_256f_r3 = sphincsPlus.Branch("14");
+        public static readonly DerObjectIdentifier sphincsPlus_shake_256s_r3 = sphincsPlus.Branch("15");
+        public static readonly DerObjectIdentifier sphincsPlus_shake_256f_r3 = sphincsPlus.Branch("16");
+        public static readonly DerObjectIdentifier sphincsPlus_haraka_256s_r3 = sphincsPlus.Branch("17");
+        public static readonly DerObjectIdentifier sphincsPlus_haraka_256f_r3 = sphincsPlus.Branch("18");
+
+        [Obsolete("Will be removed - name is erroneous")]
         public static readonly DerObjectIdentifier sphincsPlus_shake_256 = sphincsPlus.Branch("1");
+        [Obsolete("Will be removed - name is erroneous")]
         public static readonly DerObjectIdentifier sphincsPlus_sha_256 = sphincsPlus.Branch("2");
+        [Obsolete("Will be removed - name is erroneous")]
         public static readonly DerObjectIdentifier sphincsPlus_sha_512 = sphincsPlus.Branch("3");
-        
+
         /**
          * Picnic
          */
diff --git a/crypto/src/pqc/asn1/CmcePrivateKey.cs b/crypto/src/pqc/asn1/CmcePrivateKey.cs
index 44b52ca56..26df9b7a8 100644
--- a/crypto/src/pqc/asn1/CmcePrivateKey.cs
+++ b/crypto/src/pqc/asn1/CmcePrivateKey.cs
@@ -32,6 +32,11 @@ namespace Org.BouncyCastle.Pqc.Asn1
             return new CmcePrivateKey(Asn1Sequence.GetInstance(o));
         }
 
+        public static CmcePrivateKey GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
         private int version;
         private byte[] delta;
         private byte[] c;
diff --git a/crypto/src/pqc/asn1/CmcePublicKey.cs b/crypto/src/pqc/asn1/CmcePublicKey.cs
index 26bd6e438..c9feebdf5 100644
--- a/crypto/src/pqc/asn1/CmcePublicKey.cs
+++ b/crypto/src/pqc/asn1/CmcePublicKey.cs
@@ -15,7 +15,14 @@ namespace Org.BouncyCastle.Pqc.Asn1
                 return null;
             if (o is CmcePublicKey cmcePublicKey)
                 return cmcePublicKey;
+#pragma warning disable CS0618 // Type or member is obsolete
             return new CmcePublicKey(Asn1Sequence.GetInstance(o));
+#pragma warning restore CS0618 // Type or member is obsolete
+        }
+
+        public static CmcePublicKey GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private byte[] t;
@@ -25,6 +32,7 @@ namespace Org.BouncyCastle.Pqc.Asn1
             this.t = t;
         }
 
+        [Obsolete("Use 'GetInstance' instead")]
         public CmcePublicKey(Asn1Sequence seq)
         {
             t = Arrays.Clone(Asn1OctetString.GetInstance(seq[0]).GetOctets());
diff --git a/crypto/src/pqc/asn1/PqcObjectIdentifiers.cs b/crypto/src/pqc/asn1/PqcObjectIdentifiers.cs
new file mode 100644
index 000000000..94516f6f2
--- /dev/null
+++ b/crypto/src/pqc/asn1/PqcObjectIdentifiers.cs
@@ -0,0 +1,103 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.BC;
+
+namespace Org.BouncyCastle.Pqc.Asn1
+{
+    public static class PqcObjectIdentifiers
+    {
+        /** 1.3.6.1.4.1.8301.3.1.3.5.3.2 */
+        public static readonly DerObjectIdentifier rainbow = new DerObjectIdentifier("1.3.6.1.4.1.8301.3.1.3.5.3.2");
+
+        /** 1.3.6.1.4.1.8301.3.1.3.5.3.2.1 */
+        public static readonly DerObjectIdentifier rainbowWithSha1   = rainbow.Branch("1");
+        /** 1.3.6.1.4.1.8301.3.1.3.5.3.2.2 */
+        public static readonly DerObjectIdentifier rainbowWithSha224 = rainbow.Branch("2");
+        /** 1.3.6.1.4.1.8301.3.1.3.5.3.2.3 */
+        public static readonly DerObjectIdentifier rainbowWithSha256 = rainbow.Branch("3");
+        /** 1.3.6.1.4.1.8301.3.1.3.5.3.2.4 */
+        public static readonly DerObjectIdentifier rainbowWithSha384 = rainbow.Branch("4");
+        /** 1.3.6.1.4.1.8301.3.1.3.5.3.2.5 */
+        public static readonly DerObjectIdentifier rainbowWithSha512 = rainbow.Branch("5");
+
+        /** 1.3.6.1.4.1.8301.3.1.3.3 */
+        public static readonly DerObjectIdentifier gmss = new DerObjectIdentifier("1.3.6.1.4.1.8301.3.1.3.3");
+
+        /** 1.3.6.1.4.1.8301.3.1.3.3.1 */
+        public static readonly DerObjectIdentifier gmssWithSha1   = gmss.Branch("1");
+        /** 1.3.6.1.4.1.8301.3.1.3.3.2 */
+        public static readonly DerObjectIdentifier gmssWithSha224 = gmss.Branch("2");
+        /** 1.3.6.1.4.1.8301.3.1.3.3.3 */
+        public static readonly DerObjectIdentifier gmssWithSha256 = gmss.Branch("3");
+        /** 1.3.6.1.4.1.8301.3.1.3.3.4 */
+        public static readonly DerObjectIdentifier gmssWithSha384 = gmss.Branch("4");
+        /** 1.3.6.1.4.1.8301.3.1.3.3.5 */
+        public static readonly DerObjectIdentifier gmssWithSha512 = gmss.Branch("5");
+
+        /** 1.3.6.1.4.1.8301.3.1.3.4.1 */
+        public static readonly DerObjectIdentifier mcEliece       = new DerObjectIdentifier("1.3.6.1.4.1.8301.3.1.3.4.1");
+
+        /** 1.3.6.1.4.1.8301.3.1.3.4.2 */
+        public static readonly DerObjectIdentifier mcElieceCca2   = new DerObjectIdentifier("1.3.6.1.4.1.8301.3.1.3.4.2");
+
+        public static readonly DerObjectIdentifier mcElieceFujisaki    = new DerObjectIdentifier("1.3.6.1.4.1.8301.3.1.3.4.2.1");
+        public static readonly DerObjectIdentifier mcEliecePointcheval = new DerObjectIdentifier("1.3.6.1.4.1.8301.3.1.3.4.2.2");
+        public static readonly DerObjectIdentifier mcElieceKobara_Imai = new DerObjectIdentifier("1.3.6.1.4.1.8301.3.1.3.4.2.3");
+
+        public static readonly DerObjectIdentifier sphincs256 = BCObjectIdentifiers.sphincs256;
+        public static readonly DerObjectIdentifier sphincs256_with_BLAKE512 = BCObjectIdentifiers.sphincs256_with_BLAKE512;
+        public static readonly DerObjectIdentifier sphincs256_with_SHA512 = BCObjectIdentifiers.sphincs256_with_SHA512;
+        public static readonly DerObjectIdentifier sphincs256_with_SHA3_512 = BCObjectIdentifiers.sphincs256_with_SHA3_512;
+
+        public static readonly DerObjectIdentifier newHope = BCObjectIdentifiers.newHope;
+
+        /**
+         * XMSS
+         */
+        public static readonly DerObjectIdentifier xmss                      = BCObjectIdentifiers.xmss;
+        public static readonly DerObjectIdentifier xmss_SHA256ph             = BCObjectIdentifiers.xmss_SHA256ph;
+        public static readonly DerObjectIdentifier xmss_SHA512ph             = BCObjectIdentifiers.xmss_SHA512ph;
+        public static readonly DerObjectIdentifier xmss_SHAKE128ph           = BCObjectIdentifiers.xmss_SHAKE128ph;
+        public static readonly DerObjectIdentifier xmss_SHAKE256ph           = BCObjectIdentifiers.xmss_SHAKE256ph;
+        public static readonly DerObjectIdentifier xmss_SHA256               = BCObjectIdentifiers.xmss_SHA256;
+        public static readonly DerObjectIdentifier xmss_SHA512               = BCObjectIdentifiers.xmss_SHA512;
+        public static readonly DerObjectIdentifier xmss_SHAKE128             = BCObjectIdentifiers.xmss_SHAKE128;
+        public static readonly DerObjectIdentifier xmss_SHAKE256             = BCObjectIdentifiers.xmss_SHAKE256;
+
+
+        /**
+         * XMSS^MT
+         */
+        public static readonly DerObjectIdentifier xmss_mt                   = BCObjectIdentifiers.xmss_mt;
+        public static readonly DerObjectIdentifier xmss_mt_SHA256ph          = BCObjectIdentifiers.xmss_mt_SHA256ph;
+        public static readonly DerObjectIdentifier xmss_mt_SHA512ph          = BCObjectIdentifiers.xmss_mt_SHA512ph;
+        public static readonly DerObjectIdentifier xmss_mt_SHAKE128ph        = BCObjectIdentifiers.xmss_mt_SHAKE128ph;
+        public static readonly DerObjectIdentifier xmss_mt_SHAKE256ph        = BCObjectIdentifiers.xmss_mt_SHAKE256ph;
+        public static readonly DerObjectIdentifier xmss_mt_SHA256            = BCObjectIdentifiers.xmss_mt_SHA256;
+        public static readonly DerObjectIdentifier xmss_mt_SHA512            = BCObjectIdentifiers.xmss_mt_SHA512;
+        public static readonly DerObjectIdentifier xmss_mt_SHAKE128          = BCObjectIdentifiers.xmss_mt_SHAKE128;
+        public static readonly DerObjectIdentifier xmss_mt_SHAKE256          = BCObjectIdentifiers.xmss_mt_SHAKE256;
+
+        /**
+         * qTESLA
+         */
+        public static readonly DerObjectIdentifier qTESLA = BCObjectIdentifiers.qTESLA;
+        public static readonly DerObjectIdentifier qTESLA_p_I = BCObjectIdentifiers.qTESLA_p_I;
+        public static readonly DerObjectIdentifier qTESLA_p_III = BCObjectIdentifiers.qTESLA_p_III;
+
+        /**
+         * Explicit composite algorithms
+         */
+        public static readonly DerObjectIdentifier id_Dilithium3_RSA_PKCS15_SHA256 = new DerObjectIdentifier("2.16.840.1.114027.80.5.1.1");
+        public static readonly DerObjectIdentifier id_Dilithium3_ECDSA_P256_SHA256 = new DerObjectIdentifier("2.16.840.1.114027.80.5.1.2");
+        public static readonly DerObjectIdentifier id_Dilithium3_ECDSA_brainpoolP256r1_SHA256 = new DerObjectIdentifier("2.16.840.1.114027.80.5.1.3");
+        public static readonly DerObjectIdentifier id_Dilithium3_Ed25519 = new DerObjectIdentifier("2.16.840.1.114027.80.5.1.4");
+        public static readonly DerObjectIdentifier id_Dilithium5_ECDSA_P384_SHA384 = new DerObjectIdentifier("2.16.840.1.114027.80.5.1.5");
+        public static readonly DerObjectIdentifier id_Dilithium5_ECDSA_brainpoolP384r1_SHA384 = new DerObjectIdentifier("2.16.840.1.114027.80.5.1.6");
+        public static readonly DerObjectIdentifier id_Dilithium5_Ed448 = new DerObjectIdentifier("2.16.840.1.114027.80.5.1.7");
+        public static readonly DerObjectIdentifier id_Falcon512_ECDSA_P256_SHA256 = new DerObjectIdentifier("2.16.840.1.114027.80.5.1.8");
+        public static readonly DerObjectIdentifier id_Falcon512_ECDSA_brainpoolP256r1_SHA256 = new DerObjectIdentifier("2.16.840.1.114027.80.5.1.9");
+        public static readonly DerObjectIdentifier id_Falcon512_Ed25519 = new DerObjectIdentifier("2.16.840.1.114027.80.5.1.10");
+    }
+}
diff --git a/crypto/src/pqc/asn1/SphincsPlusPrivateKey.cs b/crypto/src/pqc/asn1/SphincsPlusPrivateKey.cs
new file mode 100644
index 000000000..67bef31ad
--- /dev/null
+++ b/crypto/src/pqc/asn1/SphincsPlusPrivateKey.cs
@@ -0,0 +1,96 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Pqc.Asn1
+{
+    /**
+     * See https://datatracker.ietf.org/doc/draft-uni-qsckeys-sphincsplus/00/ for details
+     * ASN.1 Encoding for a
+     * SphincsPlus private key for fully populated:
+     * <pre>
+     *   SPHINCSPLUSPrivateKey ::= SEQUENCE {
+     *     version          INTEGER {v2(1)}     --syntax version 2 (round 3)
+     *     skseed          OCTET STRING,        --n-byte private key seed
+     *     skprf           OCTET STRING,        --n-byte private key seed
+     *     PublicKey       SPHINCSPLUSPublicKey --public key
+     *   }
+     * </pre>
+     */
+    public sealed class SphincsPlusPrivateKey
+        : Asn1Encodable
+    {
+        public static SphincsPlusPrivateKey GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is SphincsPlusPrivateKey sphincsPlusPrivateKey)
+                return sphincsPlusPrivateKey;
+            return new SphincsPlusPrivateKey(Asn1Sequence.GetInstance(obj));
+        }
+
+        public static SphincsPlusPrivateKey GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
+        public SphincsPlusPrivateKey(int version, byte[] skseed, byte[] skprf)
+            : this(version, skseed, skprf, null)
+        {
+        }
+
+        public SphincsPlusPrivateKey(int version, byte[] skseed, byte[] skprf, SphincsPlusPublicKey publicKey)
+        {
+            m_version = version;
+            m_skseed = skseed;
+            m_skprf = skprf;
+            m_publicKey = publicKey;
+        }
+
+        private SphincsPlusPrivateKey(Asn1Sequence seq)
+        {
+            m_version = DerInteger.GetInstance(seq[0]).IntValueExact;
+            if (m_version != 0)
+                throw new ArgumentException("unrecognized version");
+
+            m_skseed = Arrays.Clone(Asn1OctetString.GetInstance(seq[1]).GetOctets());
+
+            m_skprf = Arrays.Clone(Asn1OctetString.GetInstance(seq[2]).GetOctets());
+
+            if (seq.Count == 4)
+            {
+                m_publicKey = SphincsPlusPublicKey.GetInstance(seq[3]);
+            }
+        }
+
+        private readonly int m_version;
+        private readonly byte[] m_skseed;
+        private readonly byte[] m_skprf;
+        private readonly SphincsPlusPublicKey m_publicKey;
+
+        public byte[] GetSkprf() => Arrays.Clone(m_skprf);
+
+        public byte[] GetSkseed() => Arrays.Clone(m_skseed);
+
+        public SphincsPlusPublicKey PublicKey => m_publicKey;
+
+        public int Version => m_version;
+
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(4);
+
+            v.Add(new DerInteger(m_version));
+            v.Add(new DerOctetString(m_skseed));
+            v.Add(new DerOctetString(m_skprf));
+
+            if (m_publicKey != null)
+            {
+                v.Add(new SphincsPlusPublicKey(m_publicKey.GetPkseed(), m_publicKey.GetPkroot()));
+            }
+
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/crypto/src/pqc/asn1/SphincsPlusPublicKey.cs b/crypto/src/pqc/asn1/SphincsPlusPublicKey.cs
new file mode 100644
index 000000000..41e2158a7
--- /dev/null
+++ b/crypto/src/pqc/asn1/SphincsPlusPublicKey.cs
@@ -0,0 +1,61 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Pqc.Asn1
+{
+    /**
+     * See https://datatracker.ietf.org/doc/draft-uni-qsckeys-sphincsplus/00/ for details.
+     * ASN.1 Encoding for a
+     * SphincsPlus public key for fully populated:
+     * <pre>
+     *   SPHINCSPPLUSPublicKey := SEQUENCE {
+     *     pkseed          OCTET STRING,     --n-byte public key seed
+     *     pkroot          OCTET STRING      --n-byte public hypertree root
+     *   }
+     * </pre>
+     */
+    public sealed class SphincsPlusPublicKey
+        : Asn1Encodable
+    {
+        public static SphincsPlusPublicKey GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is SphincsPlusPublicKey sphincsPlusPublicKey)
+                return sphincsPlusPublicKey;
+            return new SphincsPlusPublicKey(Asn1Sequence.GetInstance(obj));
+        }
+
+        public static SphincsPlusPublicKey GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
+        private readonly byte[] m_pkseed;
+        private readonly byte[] m_pkroot;
+
+        public SphincsPlusPublicKey(byte[] pkseed, byte[] pkroot)
+        {
+            m_pkseed = pkseed;
+            m_pkroot = pkroot;
+        }
+
+        private SphincsPlusPublicKey(Asn1Sequence seq)
+        {
+            m_pkseed = Arrays.Clone(Asn1OctetString.GetInstance(seq[0]).GetOctets());
+            m_pkroot = Arrays.Clone(Asn1OctetString.GetInstance(seq[1]).GetOctets());
+        }
+
+        public byte[] GetPkroot() => Arrays.Clone(m_pkroot);
+
+        public byte[] GetPkseed() => Arrays.Clone(m_pkseed);
+
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+            v.Add(new DerOctetString(m_pkseed));
+            v.Add(new DerOctetString(m_pkroot));
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/crypto/src/pqc/crypto/bike/BikeKemExtractor.cs b/crypto/src/pqc/crypto/bike/BikeKemExtractor.cs
index 75dff794c..43129e368 100644
--- a/crypto/src/pqc/crypto/bike/BikeKemExtractor.cs
+++ b/crypto/src/pqc/crypto/bike/BikeKemExtractor.cs
@@ -26,9 +26,9 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
             byte[] c0 = Arrays.CopyOfRange(encapsulation, 0, secretKey.Parameters.RByte);
             byte[] c1 = Arrays.CopyOfRange(encapsulation, secretKey.Parameters.RByte, encapsulation.Length);
 
-            byte[] h0 = secretKey.GetH0();
-            byte[] h1 = secretKey.GetH1();
-            byte[] sigma = secretKey.GetSigma();
+            byte[] h0 = secretKey.m_h0;
+            byte[] h1 = secretKey.m_h1;
+            byte[] sigma = secretKey.m_sigma;
 
             engine.Decaps(session_key, h0, h1, sigma, c0, c1);
             return Arrays.CopyOfRange(session_key, 0, defaultKeySize / 8);
diff --git a/crypto/src/pqc/crypto/bike/BikeKemGenerator.cs b/crypto/src/pqc/crypto/bike/BikeKemGenerator.cs
index 51efbd67d..0bb965235 100644
--- a/crypto/src/pqc/crypto/bike/BikeKemGenerator.cs
+++ b/crypto/src/pqc/crypto/bike/BikeKemGenerator.cs
@@ -24,7 +24,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
 
             byte[] K = new byte[parameters.LByte];
             byte[] c01 = new byte[parameters.RByte + parameters.LByte];
-            byte[] h = key.PublicKey;
+            byte[] h = key.m_publicKey;
 
             engine.Encaps(c01, K, h, sr);
 
diff --git a/crypto/src/pqc/crypto/bike/BikePrivateKeyParameters.cs b/crypto/src/pqc/crypto/bike/BikePrivateKeyParameters.cs
index 31c65e5f7..2540084d3 100644
--- a/crypto/src/pqc/crypto/bike/BikePrivateKeyParameters.cs
+++ b/crypto/src/pqc/crypto/bike/BikePrivateKeyParameters.cs
@@ -5,48 +5,24 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
     public sealed class BikePrivateKeyParameters
         : BikeKeyParameters
     {
-        // h0
-        private byte[] h0;
+        internal readonly byte[] m_h0;
+        internal readonly byte[] m_h1;
+        internal readonly byte[] m_sigma;
 
-        // h1
-        private byte[] h1;
-
-        // sigma
-        private byte[] sigma;
-
-        /**
-         * Constructor.
-         *
-         * @param h0    h0
-         * @param h1    h1
-         * @param sigma random bytes sigma
-         */
         public BikePrivateKeyParameters(BikeParameters bikeParameters, byte[] h0, byte[] h1, byte[] sigma)
             : base(true, bikeParameters)
         {
-            this.h0 = Arrays.Clone(h0);
-            this.h1 = Arrays.Clone(h1);
-            this.sigma = Arrays.Clone(sigma);
+            this.m_h0 = Arrays.Clone(h0);
+            this.m_h1 = Arrays.Clone(h1);
+            this.m_sigma = Arrays.Clone(sigma);
         }
 
-        public byte[] GetH0()
-        {
-            return h0;
-        }
+        public byte[] GetEncoded() => Arrays.ConcatenateAll(m_h0, m_h1, m_sigma);
 
-        public byte[] GetH1()
-        {
-            return h1;
-        }
+        public byte[] GetH0() => Arrays.Clone(m_h0);
 
-        public byte[] GetSigma()
-        {
-            return sigma;
-        }
+        public byte[] GetH1() => Arrays.Clone(m_h1);
 
-        public byte[] GetEncoded()
-        {
-            return Arrays.ConcatenateAll(h0, h1, sigma);
-        }
+        public byte[] GetSigma() => Arrays.Clone(m_sigma);
     }
 }
diff --git a/crypto/src/pqc/crypto/bike/BikePublicKeyParameters.cs b/crypto/src/pqc/crypto/bike/BikePublicKeyParameters.cs
index fe79fed26..aea602bb4 100644
--- a/crypto/src/pqc/crypto/bike/BikePublicKeyParameters.cs
+++ b/crypto/src/pqc/crypto/bike/BikePublicKeyParameters.cs
@@ -5,24 +5,14 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
     public sealed class BikePublicKeyParameters
         : BikeKeyParameters
     {
-        private readonly byte[] publicKey;
+        internal readonly byte[] m_publicKey;
 
-        /**
-         * Constructor.
-         *
-         * @param publicKey      byte
-         */
         public BikePublicKeyParameters(BikeParameters param, byte[] publicKey)
             : base(false, param)
         {
-            this.publicKey = Arrays.Clone(publicKey);
+            m_publicKey = Arrays.Clone(publicKey);
         }
 
-        internal byte[] PublicKey => publicKey;
-
-        public byte[] GetEncoded()
-        {
-            return Arrays.Clone(publicKey);
-        }
+        public byte[] GetEncoded() => Arrays.Clone(m_publicKey);
     }
 }
diff --git a/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusParameters.cs b/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusParameters.cs
index 8cde7cf7f..2b1f83409 100644
--- a/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusParameters.cs
+++ b/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusParameters.cs
@@ -2,6 +2,7 @@ using System;
 using System.Collections.Generic;
 
 using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
 
 namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus
 {
@@ -152,94 +153,96 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus
         private static uint sphincsPlus_haraka_256s_simple = 0x030206;
 
 
-        private static Dictionary<uint, SphincsPlusParameters> oidToParams = new Dictionary<uint, SphincsPlusParameters>();
-        private static Dictionary<SphincsPlusParameters, uint> paramsToOid = new Dictionary<SphincsPlusParameters, uint>();
+        private static readonly Dictionary<uint, SphincsPlusParameters> OidToParams =
+            new Dictionary<uint, SphincsPlusParameters>();
+        private static readonly Dictionary<SphincsPlusParameters, uint> ParamsToOid =
+            new Dictionary<SphincsPlusParameters, uint>();
 
         static SphincsPlusParameters()
         {
-            oidToParams[sphincsPlus_sha2_128f_robust] = SphincsPlusParameters.sha2_128f;
-            oidToParams[sphincsPlus_sha2_128s_robust] = SphincsPlusParameters.sha2_128s;
-            oidToParams[sphincsPlus_sha2_192f_robust] = SphincsPlusParameters.sha2_192f;
-            oidToParams[sphincsPlus_sha2_192s_robust] = SphincsPlusParameters.sha2_192s;
-            oidToParams[sphincsPlus_sha2_256f_robust] = SphincsPlusParameters.sha2_256f;
-            oidToParams[sphincsPlus_sha2_256s_robust] = SphincsPlusParameters.sha2_256s;
-
-            oidToParams[sphincsPlus_sha2_128f_simple] = SphincsPlusParameters.sha2_128f_simple;
-            oidToParams[sphincsPlus_sha2_128s_simple] = SphincsPlusParameters.sha2_128s_simple;
-            oidToParams[sphincsPlus_sha2_192f_simple] = SphincsPlusParameters.sha2_192f_simple;
-            oidToParams[sphincsPlus_sha2_192s_simple] = SphincsPlusParameters.sha2_192s_simple;
-            oidToParams[sphincsPlus_sha2_256f_simple] = SphincsPlusParameters.sha2_256f_simple;
-            oidToParams[sphincsPlus_sha2_256s_simple] = SphincsPlusParameters.sha2_256s_simple;
-
-            oidToParams[sphincsPlus_shake_128f_robust] = SphincsPlusParameters.shake_128f;
-            oidToParams[sphincsPlus_shake_128s_robust] = SphincsPlusParameters.shake_128s;
-            oidToParams[sphincsPlus_shake_192f_robust] = SphincsPlusParameters.shake_192f;
-            oidToParams[sphincsPlus_shake_192s_robust] = SphincsPlusParameters.shake_192s;
-            oidToParams[sphincsPlus_shake_256f_robust] = SphincsPlusParameters.shake_256f;
-            oidToParams[sphincsPlus_shake_256s_robust] = SphincsPlusParameters.shake_256s;
-
-            oidToParams[sphincsPlus_shake_128f_simple] = SphincsPlusParameters.shake_128f_simple;
-            oidToParams[sphincsPlus_shake_128s_simple] = SphincsPlusParameters.shake_128s_simple;
-            oidToParams[sphincsPlus_shake_192f_simple] = SphincsPlusParameters.shake_192f_simple;
-            oidToParams[sphincsPlus_shake_192s_simple] = SphincsPlusParameters.shake_192s_simple;
-            oidToParams[sphincsPlus_shake_256f_simple] = SphincsPlusParameters.shake_256f_simple;
-            oidToParams[sphincsPlus_shake_256s_simple] = SphincsPlusParameters.shake_256s_simple;
-
-            oidToParams[sphincsPlus_haraka_128f_simple] = SphincsPlusParameters.haraka_128f_simple;
-            oidToParams[sphincsPlus_haraka_128f_robust] = SphincsPlusParameters.haraka_128f;
-            oidToParams[sphincsPlus_haraka_192f_simple] = SphincsPlusParameters.haraka_192f_simple;
-            oidToParams[sphincsPlus_haraka_192f_robust] = SphincsPlusParameters.haraka_192f;
-            oidToParams[sphincsPlus_haraka_256f_simple] = SphincsPlusParameters.haraka_256f_simple;
-            oidToParams[sphincsPlus_haraka_256f_robust] = SphincsPlusParameters.haraka_256f;
-
-            oidToParams[sphincsPlus_haraka_128s_simple] = SphincsPlusParameters.haraka_128s_simple;
-            oidToParams[sphincsPlus_haraka_128s_robust] = SphincsPlusParameters.haraka_128s;
-            oidToParams[sphincsPlus_haraka_192s_simple] = SphincsPlusParameters.haraka_192s_simple;
-            oidToParams[sphincsPlus_haraka_192s_robust] = SphincsPlusParameters.haraka_192s;
-            oidToParams[sphincsPlus_haraka_256s_simple] = SphincsPlusParameters.haraka_256s_simple;
-            oidToParams[sphincsPlus_haraka_256s_robust] = SphincsPlusParameters.haraka_256s;
-
-
-            paramsToOid[SphincsPlusParameters.sha2_128f] = sphincsPlus_sha2_128f_robust;
-            paramsToOid[SphincsPlusParameters.sha2_128s] = sphincsPlus_sha2_128s_robust;
-            paramsToOid[SphincsPlusParameters.sha2_192f] = sphincsPlus_sha2_192f_robust;
-            paramsToOid[SphincsPlusParameters.sha2_192s] = sphincsPlus_sha2_192s_robust;
-            paramsToOid[SphincsPlusParameters.sha2_256f] = sphincsPlus_sha2_256f_robust;
-            paramsToOid[SphincsPlusParameters.sha2_256s] = sphincsPlus_sha2_256s_robust;
-
-            paramsToOid[SphincsPlusParameters.sha2_128f_simple] = sphincsPlus_sha2_128f_simple;
-            paramsToOid[SphincsPlusParameters.sha2_128s_simple] = sphincsPlus_sha2_128s_simple;
-            paramsToOid[SphincsPlusParameters.sha2_192f_simple] = sphincsPlus_sha2_192f_simple;
-            paramsToOid[SphincsPlusParameters.sha2_192s_simple] = sphincsPlus_sha2_192s_simple;
-            paramsToOid[SphincsPlusParameters.sha2_256f_simple] = sphincsPlus_sha2_256f_simple;
-            paramsToOid[SphincsPlusParameters.sha2_256s_simple] = sphincsPlus_sha2_256s_simple;
-
-            paramsToOid[SphincsPlusParameters.shake_128f] = sphincsPlus_shake_128f_robust;
-            paramsToOid[SphincsPlusParameters.shake_128s] = sphincsPlus_shake_128s_robust;
-            paramsToOid[SphincsPlusParameters.shake_192f] = sphincsPlus_shake_192f_robust;
-            paramsToOid[SphincsPlusParameters.shake_192s] = sphincsPlus_shake_192s_robust;
-            paramsToOid[SphincsPlusParameters.shake_256f] = sphincsPlus_shake_256f_robust;
-            paramsToOid[SphincsPlusParameters.shake_256s] = sphincsPlus_shake_256s_robust;
-
-            paramsToOid[SphincsPlusParameters.shake_128f_simple] = sphincsPlus_shake_128f_simple;
-            paramsToOid[SphincsPlusParameters.shake_128s_simple] = sphincsPlus_shake_128s_simple;
-            paramsToOid[SphincsPlusParameters.shake_192f_simple] = sphincsPlus_shake_192f_simple;
-            paramsToOid[SphincsPlusParameters.shake_192s_simple] = sphincsPlus_shake_192s_simple;
-            paramsToOid[SphincsPlusParameters.shake_256f_simple] = sphincsPlus_shake_256f_simple;
-            paramsToOid[SphincsPlusParameters.shake_256s_simple] = sphincsPlus_shake_256s_simple;
-
-            paramsToOid[SphincsPlusParameters.haraka_128f_simple] = sphincsPlus_haraka_128f_simple;
-            paramsToOid[SphincsPlusParameters.haraka_192f_simple] = sphincsPlus_haraka_192f_simple;
-            paramsToOid[SphincsPlusParameters.haraka_256f_simple] = sphincsPlus_haraka_256f_simple;
-            paramsToOid[SphincsPlusParameters.haraka_128s_simple] = sphincsPlus_haraka_128s_simple;
-            paramsToOid[SphincsPlusParameters.haraka_192s_simple] = sphincsPlus_haraka_192s_simple;
-            paramsToOid[SphincsPlusParameters.haraka_256s_simple] = sphincsPlus_haraka_256s_simple;
-            paramsToOid[SphincsPlusParameters.haraka_128f] = sphincsPlus_haraka_128f_robust;
-            paramsToOid[SphincsPlusParameters.haraka_192f] = sphincsPlus_haraka_192f_robust;
-            paramsToOid[SphincsPlusParameters.haraka_256f] = sphincsPlus_haraka_256f_robust;
-            paramsToOid[SphincsPlusParameters.haraka_128s] = sphincsPlus_haraka_128s_robust;
-            paramsToOid[SphincsPlusParameters.haraka_192s] = sphincsPlus_haraka_192s_robust;
-            paramsToOid[SphincsPlusParameters.haraka_256s] = sphincsPlus_haraka_256s_robust;
+            OidToParams[sphincsPlus_sha2_128f_robust] = SphincsPlusParameters.sha2_128f;
+            OidToParams[sphincsPlus_sha2_128s_robust] = SphincsPlusParameters.sha2_128s;
+            OidToParams[sphincsPlus_sha2_192f_robust] = SphincsPlusParameters.sha2_192f;
+            OidToParams[sphincsPlus_sha2_192s_robust] = SphincsPlusParameters.sha2_192s;
+            OidToParams[sphincsPlus_sha2_256f_robust] = SphincsPlusParameters.sha2_256f;
+            OidToParams[sphincsPlus_sha2_256s_robust] = SphincsPlusParameters.sha2_256s;
+
+            OidToParams[sphincsPlus_sha2_128f_simple] = SphincsPlusParameters.sha2_128f_simple;
+            OidToParams[sphincsPlus_sha2_128s_simple] = SphincsPlusParameters.sha2_128s_simple;
+            OidToParams[sphincsPlus_sha2_192f_simple] = SphincsPlusParameters.sha2_192f_simple;
+            OidToParams[sphincsPlus_sha2_192s_simple] = SphincsPlusParameters.sha2_192s_simple;
+            OidToParams[sphincsPlus_sha2_256f_simple] = SphincsPlusParameters.sha2_256f_simple;
+            OidToParams[sphincsPlus_sha2_256s_simple] = SphincsPlusParameters.sha2_256s_simple;
+
+            OidToParams[sphincsPlus_shake_128f_robust] = SphincsPlusParameters.shake_128f;
+            OidToParams[sphincsPlus_shake_128s_robust] = SphincsPlusParameters.shake_128s;
+            OidToParams[sphincsPlus_shake_192f_robust] = SphincsPlusParameters.shake_192f;
+            OidToParams[sphincsPlus_shake_192s_robust] = SphincsPlusParameters.shake_192s;
+            OidToParams[sphincsPlus_shake_256f_robust] = SphincsPlusParameters.shake_256f;
+            OidToParams[sphincsPlus_shake_256s_robust] = SphincsPlusParameters.shake_256s;
+
+            OidToParams[sphincsPlus_shake_128f_simple] = SphincsPlusParameters.shake_128f_simple;
+            OidToParams[sphincsPlus_shake_128s_simple] = SphincsPlusParameters.shake_128s_simple;
+            OidToParams[sphincsPlus_shake_192f_simple] = SphincsPlusParameters.shake_192f_simple;
+            OidToParams[sphincsPlus_shake_192s_simple] = SphincsPlusParameters.shake_192s_simple;
+            OidToParams[sphincsPlus_shake_256f_simple] = SphincsPlusParameters.shake_256f_simple;
+            OidToParams[sphincsPlus_shake_256s_simple] = SphincsPlusParameters.shake_256s_simple;
+
+            OidToParams[sphincsPlus_haraka_128f_simple] = SphincsPlusParameters.haraka_128f_simple;
+            OidToParams[sphincsPlus_haraka_128f_robust] = SphincsPlusParameters.haraka_128f;
+            OidToParams[sphincsPlus_haraka_192f_simple] = SphincsPlusParameters.haraka_192f_simple;
+            OidToParams[sphincsPlus_haraka_192f_robust] = SphincsPlusParameters.haraka_192f;
+            OidToParams[sphincsPlus_haraka_256f_simple] = SphincsPlusParameters.haraka_256f_simple;
+            OidToParams[sphincsPlus_haraka_256f_robust] = SphincsPlusParameters.haraka_256f;
+
+            OidToParams[sphincsPlus_haraka_128s_simple] = SphincsPlusParameters.haraka_128s_simple;
+            OidToParams[sphincsPlus_haraka_128s_robust] = SphincsPlusParameters.haraka_128s;
+            OidToParams[sphincsPlus_haraka_192s_simple] = SphincsPlusParameters.haraka_192s_simple;
+            OidToParams[sphincsPlus_haraka_192s_robust] = SphincsPlusParameters.haraka_192s;
+            OidToParams[sphincsPlus_haraka_256s_simple] = SphincsPlusParameters.haraka_256s_simple;
+            OidToParams[sphincsPlus_haraka_256s_robust] = SphincsPlusParameters.haraka_256s;
+
+
+            ParamsToOid[SphincsPlusParameters.sha2_128f] = sphincsPlus_sha2_128f_robust;
+            ParamsToOid[SphincsPlusParameters.sha2_128s] = sphincsPlus_sha2_128s_robust;
+            ParamsToOid[SphincsPlusParameters.sha2_192f] = sphincsPlus_sha2_192f_robust;
+            ParamsToOid[SphincsPlusParameters.sha2_192s] = sphincsPlus_sha2_192s_robust;
+            ParamsToOid[SphincsPlusParameters.sha2_256f] = sphincsPlus_sha2_256f_robust;
+            ParamsToOid[SphincsPlusParameters.sha2_256s] = sphincsPlus_sha2_256s_robust;
+
+            ParamsToOid[SphincsPlusParameters.sha2_128f_simple] = sphincsPlus_sha2_128f_simple;
+            ParamsToOid[SphincsPlusParameters.sha2_128s_simple] = sphincsPlus_sha2_128s_simple;
+            ParamsToOid[SphincsPlusParameters.sha2_192f_simple] = sphincsPlus_sha2_192f_simple;
+            ParamsToOid[SphincsPlusParameters.sha2_192s_simple] = sphincsPlus_sha2_192s_simple;
+            ParamsToOid[SphincsPlusParameters.sha2_256f_simple] = sphincsPlus_sha2_256f_simple;
+            ParamsToOid[SphincsPlusParameters.sha2_256s_simple] = sphincsPlus_sha2_256s_simple;
+
+            ParamsToOid[SphincsPlusParameters.shake_128f] = sphincsPlus_shake_128f_robust;
+            ParamsToOid[SphincsPlusParameters.shake_128s] = sphincsPlus_shake_128s_robust;
+            ParamsToOid[SphincsPlusParameters.shake_192f] = sphincsPlus_shake_192f_robust;
+            ParamsToOid[SphincsPlusParameters.shake_192s] = sphincsPlus_shake_192s_robust;
+            ParamsToOid[SphincsPlusParameters.shake_256f] = sphincsPlus_shake_256f_robust;
+            ParamsToOid[SphincsPlusParameters.shake_256s] = sphincsPlus_shake_256s_robust;
+
+            ParamsToOid[SphincsPlusParameters.shake_128f_simple] = sphincsPlus_shake_128f_simple;
+            ParamsToOid[SphincsPlusParameters.shake_128s_simple] = sphincsPlus_shake_128s_simple;
+            ParamsToOid[SphincsPlusParameters.shake_192f_simple] = sphincsPlus_shake_192f_simple;
+            ParamsToOid[SphincsPlusParameters.shake_192s_simple] = sphincsPlus_shake_192s_simple;
+            ParamsToOid[SphincsPlusParameters.shake_256f_simple] = sphincsPlus_shake_256f_simple;
+            ParamsToOid[SphincsPlusParameters.shake_256s_simple] = sphincsPlus_shake_256s_simple;
+
+            ParamsToOid[SphincsPlusParameters.haraka_128f_simple] = sphincsPlus_haraka_128f_simple;
+            ParamsToOid[SphincsPlusParameters.haraka_192f_simple] = sphincsPlus_haraka_192f_simple;
+            ParamsToOid[SphincsPlusParameters.haraka_256f_simple] = sphincsPlus_haraka_256f_simple;
+            ParamsToOid[SphincsPlusParameters.haraka_128s_simple] = sphincsPlus_haraka_128s_simple;
+            ParamsToOid[SphincsPlusParameters.haraka_192s_simple] = sphincsPlus_haraka_192s_simple;
+            ParamsToOid[SphincsPlusParameters.haraka_256s_simple] = sphincsPlus_haraka_256s_simple;
+            ParamsToOid[SphincsPlusParameters.haraka_128f] = sphincsPlus_haraka_128f_robust;
+            ParamsToOid[SphincsPlusParameters.haraka_192f] = sphincsPlus_haraka_192f_robust;
+            ParamsToOid[SphincsPlusParameters.haraka_256f] = sphincsPlus_haraka_256f_robust;
+            ParamsToOid[SphincsPlusParameters.haraka_128s] = sphincsPlus_haraka_128s_robust;
+            ParamsToOid[SphincsPlusParameters.haraka_192s] = sphincsPlus_haraka_192s_robust;
+            ParamsToOid[SphincsPlusParameters.haraka_256s] = sphincsPlus_haraka_256s_robust;
         }
 
         private readonly string m_name;
@@ -268,7 +271,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus
          */
         public static SphincsPlusParameters GetParams(int id)
         {
-            return oidToParams[Convert.ToUInt32(id)];
+            return CollectionUtilities.GetValueOrNull(OidToParams, Convert.ToUInt32(id));
         }
 
         /**
@@ -279,7 +282,10 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus
          */
         public static int GetID(SphincsPlusParameters parameters)
         {
-            return Convert.ToInt32(paramsToOid[parameters]);
+            if (ParamsToOid.TryGetValue(parameters, out uint value))
+                return Convert.ToInt32(value);
+
+            return -1;
         }
 
         public byte[] GetEncoded()
diff --git a/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusPrivateKeyParameters.cs b/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusPrivateKeyParameters.cs
index 55757b927..de9dae2ce 100644
--- a/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusPrivateKeyParameters.cs
+++ b/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusPrivateKeyParameters.cs
@@ -1,6 +1,5 @@
 using System;
 
-using Org.BouncyCastle.Crypto.Utilities;
 using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus
@@ -16,14 +15,20 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus
         {
             int n = parameters.N;
             if (skpkEncoded.Length != 4 * n)
-            {
                 throw new ArgumentException("private key encoding does not match parameters");
-            }
 
             m_sk = new SK(Arrays.CopyOfRange(skpkEncoded, 0, n), Arrays.CopyOfRange(skpkEncoded, n, 2 * n));
             m_pk = new PK(Arrays.CopyOfRange(skpkEncoded, 2 * n, 3 * n), Arrays.CopyOfRange(skpkEncoded, 3 * n, 4 * n));
         }
 
+        public SphincsPlusPrivateKeyParameters(SphincsPlusParameters parameters, byte[] skSeed, byte[] prf,
+            byte[] pkSeed, byte[] pkRoot)
+            : base(true, parameters)
+        {
+            m_sk = new SK(skSeed, prf);
+            m_pk = new PK(pkSeed, pkRoot);
+        }
+
         internal SphincsPlusPrivateKeyParameters(SphincsPlusParameters parameters, SK sk, PK pk)
             : base(true, parameters)
         {
@@ -31,19 +36,19 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus
             m_pk = pk;
         }
 
-        public byte[] GetSeed()
+        public byte[] GetEncoded()
         {
-            return Arrays.Clone(m_sk.seed);
+            return Arrays.ConcatenateAll(Parameters.GetEncoded(), m_sk.seed, m_sk.prf, m_pk.seed, m_pk.root);
         }
 
-        public byte[] GetPrf()
+        public byte[] GetEncodedPublicKey()
         {
-            return Arrays.Clone(m_sk.prf);
+            return Arrays.ConcatenateAll(Parameters.GetEncoded(), m_pk.seed, m_pk.root);
         }
 
-        public byte[] GetPublicSeed()
+        public byte[] GetPrf()
         {
-            return Arrays.Clone(m_pk.seed);
+            return Arrays.Clone(m_sk.prf);
         }
 
         public byte[] GetPublicKey()
@@ -51,16 +56,19 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus
             return Arrays.Concatenate(m_pk.seed, m_pk.root);
         }
 
-        public byte[] GetEncoded()
+        public byte[] GetPublicSeed()
         {
-            var id = Pack.UInt32_To_BE((uint)SphincsPlusParameters.GetID(Parameters));
-            return Arrays.ConcatenateAll(id, m_sk.seed, m_sk.prf, m_pk.seed, m_pk.root);
+            return Arrays.Clone(m_pk.seed);
         }
 
-        public byte[] GetEncodedPublicKey()
+        public byte[] GetRoot()
         {
-            var id = Pack.UInt32_To_BE((uint)SphincsPlusParameters.GetID(Parameters));
-            return Arrays.ConcatenateAll(id, m_pk.seed, m_pk.root);
+            return Arrays.Clone(m_pk.root);
+        }
+
+        public byte[] GetSeed()
+        {
+            return Arrays.Clone(m_sk.seed);
         }
     }
 }
diff --git a/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusPublicKeyParameters.cs b/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusPublicKeyParameters.cs
index b34843998..13028ea1b 100644
--- a/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusPublicKeyParameters.cs
+++ b/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusPublicKeyParameters.cs
@@ -1,6 +1,5 @@
 using System;
 
-using Org.BouncyCastle.Crypto.Utilities;
 using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus
@@ -26,9 +25,9 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus
             m_pk = pk;
         }
 
-        public byte[] GetSeed()
+        public byte[] GetEncoded()
         {
-            return Arrays.Clone(m_pk.seed);
+            return Arrays.ConcatenateAll(Parameters.GetEncoded(), m_pk.seed, m_pk.root);
         }
 
         public byte[] GetRoot()
@@ -36,10 +35,9 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus
             return Arrays.Clone(m_pk.root);
         }
 
-        public byte[] GetEncoded()
+        public byte[] GetSeed()
         {
-            var id = Pack.UInt32_To_BE((uint)SphincsPlusParameters.GetID(Parameters));
-            return Arrays.ConcatenateAll(id, m_pk.seed, m_pk.root);
+            return Arrays.Clone(m_pk.seed);
         }
     }
 }
diff --git a/crypto/src/pqc/crypto/utils/PqcPrivateKeyFactory.cs b/crypto/src/pqc/crypto/utils/PqcPrivateKeyFactory.cs
index 1deb2c8d6..469fbf0fe 100644
--- a/crypto/src/pqc/crypto/utils/PqcPrivateKeyFactory.cs
+++ b/crypto/src/pqc/crypto/utils/PqcPrivateKeyFactory.cs
@@ -51,10 +51,10 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
         /// <exception cref="IOException"> on an error decoding the key</exception>
         public static AsymmetricKeyParameter CreateKey(PrivateKeyInfo keyInfo)
         {
-            AlgorithmIdentifier algId = keyInfo.PrivateKeyAlgorithm;
-            DerObjectIdentifier algOID = algId.Algorithm;
+            AlgorithmIdentifier algID = keyInfo.PrivateKeyAlgorithm;
+            DerObjectIdentifier algOid = algID.Algorithm;
 
-            if (algOID.Equals(PkcsObjectIdentifiers.IdAlgHssLmsHashsig))
+            if (algOid.Equals(PkcsObjectIdentifiers.IdAlgHssLmsHashsig))
             {
                 byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePrivateKey()).GetOctets();
                 DerBitString pubKey = keyInfo.PublicKeyData;
@@ -72,54 +72,56 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
                     return LmsPrivateKeyParameters.GetInstance(Arrays.CopyOfRange(keyEnc, 4, keyEnc.Length));
                 }
             }
-            if (algOID.On(BCObjectIdentifiers.pqc_kem_mceliece))
+            if (algOid.On(BCObjectIdentifiers.pqc_kem_mceliece))
             {
                 CmcePrivateKey cmceKey = CmcePrivateKey.GetInstance(keyInfo.ParsePrivateKey());
-                CmceParameters spParams = PqcUtilities.McElieceParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm);
+                CmceParameters spParams = PqcUtilities.McElieceParamsLookup(algOid);
 
                 return new CmcePrivateKeyParameters(spParams, cmceKey.Delta, cmceKey.C, cmceKey.G, cmceKey.Alpha, cmceKey.S);
             }
-            if (algOID.On(BCObjectIdentifiers.pqc_kem_frodo))
+            if (algOid.On(BCObjectIdentifiers.pqc_kem_frodo))
             {
                 byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePrivateKey()).GetOctets();
-                FrodoParameters spParams = PqcUtilities.FrodoParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm);
+                FrodoParameters spParams = PqcUtilities.FrodoParamsLookup(algOid);
 
                 return new FrodoPrivateKeyParameters(spParams, keyEnc);
             }
-            if (algOID.On(BCObjectIdentifiers.sphincsPlus))
+            if (algOid.On(BCObjectIdentifiers.sphincsPlus))
             {
-                byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePrivateKey()).GetOctets();
-                SphincsPlusParameters spParams = SphincsPlusParameters.GetParams(BigInteger.ValueOf(Pack.BE_To_UInt32(keyEnc, 0)).IntValue);
+                SphincsPlusPrivateKey spKey = SphincsPlusPrivateKey.GetInstance(keyInfo.ParsePrivateKey());
+                SphincsPlusParameters spParams = PqcUtilities.SphincsPlusParamsLookup(algOid);
+                SphincsPlusPublicKey publicKey = spKey.PublicKey;
 
-                return new SphincsPlusPrivateKeyParameters(spParams, Arrays.CopyOfRange(keyEnc, 4, keyEnc.Length));
+                return new SphincsPlusPrivateKeyParameters(spParams, spKey.GetSkseed(), spKey.GetSkprf(),
+                    publicKey.GetPkseed(), publicKey.GetPkroot());
             }
-            if (algOID.On(BCObjectIdentifiers.pqc_kem_saber))
+            if (algOid.On(BCObjectIdentifiers.pqc_kem_saber))
             {
                 byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePrivateKey()).GetOctets();
-                SaberParameters spParams = PqcUtilities.SaberParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm);
+                SaberParameters spParams = PqcUtilities.SaberParamsLookup(algOid);
 
                 return new SaberPrivateKeyParameters(spParams, keyEnc);
             }
-            if (algOID.On(BCObjectIdentifiers.picnic))
+            if (algOid.On(BCObjectIdentifiers.picnic))
             {
                 byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePrivateKey()).GetOctets();
-                PicnicParameters picnicParams = PqcUtilities.PicnicParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm);
+                PicnicParameters picnicParams = PqcUtilities.PicnicParamsLookup(algOid);
 
                 return new PicnicPrivateKeyParameters(picnicParams, keyEnc);
             }
 #pragma warning disable CS0618 // Type or member is obsolete
-            if (algOID.On(BCObjectIdentifiers.pqc_kem_sike))
+            if (algOid.On(BCObjectIdentifiers.pqc_kem_sike))
             {
                 byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePrivateKey()).GetOctets();
-                SikeParameters sikeParams = PqcUtilities.SikeParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm);
+                SikeParameters sikeParams = PqcUtilities.SikeParamsLookup(algOid);
 
                 return new SikePrivateKeyParameters(sikeParams, keyEnc);
             }
 #pragma warning restore CS0618 // Type or member is obsolete
-            if (algOID.On(BCObjectIdentifiers.pqc_kem_bike))
+            if (algOid.On(BCObjectIdentifiers.pqc_kem_bike))
             {
                 byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePrivateKey()).GetOctets();
-                BikeParameters bikeParams = PqcUtilities.BikeParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm);
+                BikeParameters bikeParams = PqcUtilities.BikeParamsLookup(algOid);
 
                 byte[] h0 = Arrays.CopyOfRange(keyEnc, 0, bikeParams.RByte);
                 byte[] h1 = Arrays.CopyOfRange(keyEnc, bikeParams.RByte, 2 * bikeParams.RByte);
@@ -127,17 +129,17 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
 
                 return new BikePrivateKeyParameters(bikeParams, h0, h1, sigma);
             }
-            if (algOID.On(BCObjectIdentifiers.pqc_kem_hqc))
+            if (algOid.On(BCObjectIdentifiers.pqc_kem_hqc))
             {
                 byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePrivateKey()).GetOctets();
-                HqcParameters hqcParams = PqcUtilities.HqcParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm);
+                HqcParameters hqcParams = PqcUtilities.HqcParamsLookup(algOid);
 
                 return new HqcPrivateKeyParameters(hqcParams, keyEnc);
             }
-            if (algOID.On(BCObjectIdentifiers.pqc_kem_kyber))
+            if (algOid.On(BCObjectIdentifiers.pqc_kem_kyber))
             {
                 KyberPrivateKey kyberKey = KyberPrivateKey.GetInstance(keyInfo.ParsePrivateKey());
-                KyberParameters kyberParams = PqcUtilities.KyberParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm);
+                KyberParameters kyberParams = PqcUtilities.KyberParamsLookup(algOid);
 
 #pragma warning disable CS0618 // Type or member is obsolete
                 KyberPublicKey pubKey = kyberKey.PublicKey;
@@ -150,17 +152,16 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
                 return new KyberPrivateKeyParameters(kyberParams, kyberKey.GetS(), kyberKey.GetHpk(),
                     kyberKey.GetNonce(), 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))
+            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);
+                DilithiumParameters spParams = PqcUtilities.DilithiumParamsLookup(algOid);
 
                 int version = DerInteger.GetInstance(keyEnc[0]).IntValueExact;
                 if (version != 0)
@@ -190,10 +191,11 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
                         null);
                 }
             }
-            if (algOID.Equals(BCObjectIdentifiers.falcon_512) || algOID.Equals(BCObjectIdentifiers.falcon_1024))
+            if (algOid.Equals(BCObjectIdentifiers.falcon_512) ||
+                algOid.Equals(BCObjectIdentifiers.falcon_1024))
             {
                 Asn1Sequence keyEnc = Asn1Sequence.GetInstance(keyInfo.ParsePrivateKey());
-                FalconParameters spParams = PqcUtilities.FalconParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm);
+                FalconParameters spParams = PqcUtilities.FalconParamsLookup(algOid);
                     
                 DerBitString publicKeyData = keyInfo.PublicKeyData;
                 int version = DerInteger.GetInstance(keyEnc[0]).IntValueExact;
diff --git a/crypto/src/pqc/crypto/utils/PqcPrivateKeyInfoFactory.cs b/crypto/src/pqc/crypto/utils/PqcPrivateKeyInfoFactory.cs
index 3e2832713..5e11c6d1d 100644
--- a/crypto/src/pqc/crypto/utils/PqcPrivateKeyInfoFactory.cs
+++ b/crypto/src/pqc/crypto/utils/PqcPrivateKeyInfoFactory.cs
@@ -58,12 +58,14 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
             }
             if (privateKey is SphincsPlusPrivateKeyParameters sphincsPlusPrivateKeyParameters)
             {
-                byte[] encoding = sphincsPlusPrivateKeyParameters.GetEncoded();
-                byte[] pubEncoding = sphincsPlusPrivateKeyParameters.GetEncodedPublicKey();
-
                 AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
                     PqcUtilities.SphincsPlusOidLookup(sphincsPlusPrivateKeyParameters.Parameters));
-                return new PrivateKeyInfo(algorithmIdentifier, new DerOctetString(encoding), attributes, pubEncoding);
+                SphincsPlusPublicKey spPub = new SphincsPlusPublicKey(sphincsPlusPrivateKeyParameters.GetPublicSeed(),
+                    sphincsPlusPrivateKeyParameters.GetRoot());
+                SphincsPlusPrivateKey spPriv = new SphincsPlusPrivateKey(0, sphincsPlusPrivateKeyParameters.GetSeed(),
+                    sphincsPlusPrivateKeyParameters.GetPrf(), spPub);
+
+                return new PrivateKeyInfo(algorithmIdentifier, spPriv, attributes);
             }
             if (privateKey is CmcePrivateKeyParameters cmcePrivateKeyParameters)
             {
diff --git a/crypto/src/pqc/crypto/utils/PqcPublicKeyFactory.cs b/crypto/src/pqc/crypto/utils/PqcPublicKeyFactory.cs
index 899ebc28e..b72bb8666 100644
--- a/crypto/src/pqc/crypto/utils/PqcPublicKeyFactory.cs
+++ b/crypto/src/pqc/crypto/utils/PqcPublicKeyFactory.cs
@@ -34,11 +34,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
         static PqcPublicKeyFactory()
         {
             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();
@@ -126,6 +121,27 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
             Converters[BCObjectIdentifiers.hqc128] = new HqcConverter();
             Converters[BCObjectIdentifiers.hqc192] = new HqcConverter();
             Converters[BCObjectIdentifiers.hqc256] = new HqcConverter();
+
+
+            Converters[BCObjectIdentifiers.sphincsPlus] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_sha2_128s_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_sha2_128f_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_shake_128s_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_shake_128f_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_haraka_128s_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_haraka_128f_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_sha2_192s_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_sha2_192f_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_shake_192s_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_shake_192f_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_haraka_192s_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_haraka_192f_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_sha2_256s_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_sha2_256f_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_shake_256s_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_shake_256f_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_haraka_256s_r3] = new SphincsPlusConverter();
+            Converters[BCObjectIdentifiers.sphincsPlus_haraka_256f_r3] = new SphincsPlusConverter();
         }
 
         /// <summary> Create a public key from a SubjectPublicKeyInfo encoding</summary>
@@ -206,7 +222,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
             {
                 byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePublicKey()).GetOctets();
 
-                SphincsPlusParameters spParams = SphincsPlusParameters.GetParams((int)Pack.BE_To_UInt32(keyEnc, 0));
+                SphincsPlusParameters spParams = PqcUtilities.SphincsPlusParamsLookup(keyInfo.AlgorithmID.Algorithm);
 
                 return new SphincsPlusPublicKeyParameters(spParams, Arrays.CopyOfRange(keyEnc, 4, keyEnc.Length));
             }
diff --git a/crypto/src/pqc/crypto/utils/PqcUtilities.cs b/crypto/src/pqc/crypto/utils/PqcUtilities.cs
index 101e3c846..9174dd71b 100644
--- a/crypto/src/pqc/crypto/utils/PqcUtilities.cs
+++ b/crypto/src/pqc/crypto/utils/PqcUtilities.cs
@@ -51,6 +51,9 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
         private readonly static Dictionary<HqcParameters, DerObjectIdentifier> hqcOids = new Dictionary<HqcParameters, DerObjectIdentifier>();
         private readonly static Dictionary<DerObjectIdentifier, HqcParameters> hqcParams = new Dictionary<DerObjectIdentifier, HqcParameters>();
 
+        private readonly static Dictionary<SphincsPlusParameters, DerObjectIdentifier> sphincsPlusOids = new Dictionary<SphincsPlusParameters, DerObjectIdentifier>();
+        private readonly static Dictionary<DerObjectIdentifier, SphincsPlusParameters> sphincsPlusParams = new Dictionary<DerObjectIdentifier, SphincsPlusParameters>();
+
         static PqcUtilities()
         {
             // CMCE
@@ -224,6 +227,44 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
             hqcOids[HqcParameters.hqc128] = BCObjectIdentifiers.hqc128;
             hqcOids[HqcParameters.hqc192] = BCObjectIdentifiers.hqc192;
             hqcOids[HqcParameters.hqc256] = BCObjectIdentifiers.hqc256;
+
+            sphincsPlusOids[SphincsPlusParameters.sha2_128s] = BCObjectIdentifiers.sphincsPlus_sha2_128s_r3;
+            sphincsPlusOids[SphincsPlusParameters.sha2_128f] = BCObjectIdentifiers.sphincsPlus_sha2_128f_r3;
+            sphincsPlusOids[SphincsPlusParameters.shake_128s] = BCObjectIdentifiers.sphincsPlus_shake_128s_r3;
+            sphincsPlusOids[SphincsPlusParameters.shake_128f] = BCObjectIdentifiers.sphincsPlus_shake_128f_r3;
+            sphincsPlusOids[SphincsPlusParameters.haraka_128s] = BCObjectIdentifiers.sphincsPlus_haraka_128s_r3;
+            sphincsPlusOids[SphincsPlusParameters.haraka_128f] = BCObjectIdentifiers.sphincsPlus_haraka_128f_r3;
+            sphincsPlusOids[SphincsPlusParameters.sha2_192s] = BCObjectIdentifiers.sphincsPlus_sha2_192s_r3;
+            sphincsPlusOids[SphincsPlusParameters.sha2_192f] = BCObjectIdentifiers.sphincsPlus_sha2_192f_r3;
+            sphincsPlusOids[SphincsPlusParameters.shake_192s] = BCObjectIdentifiers.sphincsPlus_shake_192s_r3;
+            sphincsPlusOids[SphincsPlusParameters.shake_192f] = BCObjectIdentifiers.sphincsPlus_shake_192f_r3;
+            sphincsPlusOids[SphincsPlusParameters.haraka_192s] = BCObjectIdentifiers.sphincsPlus_haraka_192s_r3;
+            sphincsPlusOids[SphincsPlusParameters.haraka_192f] = BCObjectIdentifiers.sphincsPlus_haraka_192f_r3;
+            sphincsPlusOids[SphincsPlusParameters.sha2_256s] = BCObjectIdentifiers.sphincsPlus_sha2_256s_r3;
+            sphincsPlusOids[SphincsPlusParameters.sha2_256f] = BCObjectIdentifiers.sphincsPlus_sha2_256f_r3;
+            sphincsPlusOids[SphincsPlusParameters.shake_256s] = BCObjectIdentifiers.sphincsPlus_shake_256s_r3;
+            sphincsPlusOids[SphincsPlusParameters.shake_256f] = BCObjectIdentifiers.sphincsPlus_shake_256f_r3;
+            sphincsPlusOids[SphincsPlusParameters.haraka_256s] = BCObjectIdentifiers.sphincsPlus_haraka_256s_r3;
+            sphincsPlusOids[SphincsPlusParameters.haraka_256f] = BCObjectIdentifiers.sphincsPlus_haraka_256f_r3;
+
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_sha2_128s_r3] = SphincsPlusParameters.sha2_128s;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_sha2_128f_r3] = SphincsPlusParameters.sha2_128f;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_shake_128s_r3] = SphincsPlusParameters.shake_128s;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_shake_128f_r3] = SphincsPlusParameters.shake_128f;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_haraka_128s_r3] = SphincsPlusParameters.haraka_128s;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_haraka_128f_r3] = SphincsPlusParameters.haraka_128f;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_sha2_192s_r3] = SphincsPlusParameters.sha2_192s;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_sha2_192f_r3] = SphincsPlusParameters.sha2_192f;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_shake_192s_r3] = SphincsPlusParameters.shake_192s;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_shake_192f_r3] = SphincsPlusParameters.shake_192f;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_haraka_192s_r3] = SphincsPlusParameters.haraka_192s;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_haraka_192f_r3] = SphincsPlusParameters.haraka_192f;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_sha2_256s_r3] = SphincsPlusParameters.sha2_256s;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_sha2_256f_r3] = SphincsPlusParameters.sha2_256f;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_shake_256s_r3] = SphincsPlusParameters.shake_256s;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_shake_256f_r3] = SphincsPlusParameters.shake_256f;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_haraka_256s_r3] = SphincsPlusParameters.haraka_256s;
+            sphincsPlusParams[BCObjectIdentifiers.sphincsPlus_haraka_256f_r3] = SphincsPlusParameters.haraka_256f;
         }
 
         internal static DerObjectIdentifier McElieceOidLookup(CmceParameters parameters)
@@ -286,19 +327,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
             return CollectionUtilities.GetValueOrNull(dilithiumOids, parameters);
         }
 
-        internal static DerObjectIdentifier SphincsPlusOidLookup(SphincsPlusParameters parameters)
-        {
-            int pId = SphincsPlusParameters.GetID(parameters);
-
-            if ((pId & 0x020000) == 0x020000)
-                return BCObjectIdentifiers.sphincsPlus_shake_256;
-
-            if ((pId & 0x05) == 0x05 || (pId & 0x06) == 0x06)
-                return BCObjectIdentifiers.sphincsPlus_sha_512;
-
-            return BCObjectIdentifiers.sphincsPlus_sha_256;
-        }
-
         internal static DerObjectIdentifier PicnicOidLookup(PicnicParameters parameters)
         {
             return CollectionUtilities.GetValueOrNull(picnicOids, parameters);
@@ -340,5 +368,15 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
         {
             return CollectionUtilities.GetValueOrNull(hqcParams, oid);
         }
+
+        internal static DerObjectIdentifier SphincsPlusOidLookup(SphincsPlusParameters parameters)
+        {
+            return CollectionUtilities.GetValueOrNull(sphincsPlusOids, parameters);
+        }
+
+        internal static SphincsPlusParameters SphincsPlusParamsLookup(DerObjectIdentifier oid)
+        {
+            return CollectionUtilities.GetValueOrNull(sphincsPlusParams, oid);
+        }
     }
 }
diff --git a/crypto/test/src/pqc/crypto/test/SphincsPlusTest.cs b/crypto/test/src/pqc/crypto/test/SphincsPlusTest.cs
index 4e60c3351..2f46a6028 100644
--- a/crypto/test/src/pqc/crypto/test/SphincsPlusTest.cs
+++ b/crypto/test/src/pqc/crypto/test/SphincsPlusTest.cs
@@ -453,6 +453,15 @@ namespace Org.BouncyCastle.Pqc.Crypto.Tests
             SphincsPlusPublicKeyParameters pubParams = (SphincsPlusPublicKeyParameters)kp.Public;
             SphincsPlusPrivateKeyParameters privParams = (SphincsPlusPrivateKeyParameters)kp.Private;
 
+            // FIXME No OIDs for simple variants of SPHINCS+
+            if (!name.Contains("-simple"))
+            {
+                pubParams = (SphincsPlusPublicKeyParameters)PqcPublicKeyFactory.CreateKey(
+                    PqcSubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubParams));
+                privParams = (SphincsPlusPrivateKeyParameters)PqcPrivateKeyFactory.CreateKey(
+                    PqcPrivateKeyInfoFactory.CreatePrivateKeyInfo(privParams));
+            }
+
             Assert.True(Arrays.AreEqual(Arrays.Concatenate(pubParams.Parameters.GetEncoded(), pk), pubParams.GetEncoded()), name + " " + count + ": public key");
             Assert.True(Arrays.AreEqual(Arrays.Concatenate(privParams.Parameters.GetEncoded(), sk), privParams.GetEncoded()), name + " " + count + ": secret key");