summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2023-04-18 22:04:16 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2023-04-18 22:04:16 +0700
commit60cd331972c01dc7c5e0d78de67c5fcc8bf2b007 (patch)
tree3e9893020957d9bc12785a55f257296e8b869551
parentRemove unused variable (diff)
downloadBouncyCastle.NET-ed25519-60cd331972c01dc7c5e0d78de67c5fcc8bf2b007.tar.xz
Update Kyber public key encoding
-rw-r--r--crypto/src/pqc/asn1/KyberPublicKey.cs60
-rw-r--r--crypto/src/pqc/crypto/utils/PqcPublicKeyFactory.cs40
-rw-r--r--crypto/src/pqc/crypto/utils/PqcSubjectPublicKeyInfoFactory.cs6
3 files changed, 81 insertions, 25 deletions
diff --git a/crypto/src/pqc/asn1/KyberPublicKey.cs b/crypto/src/pqc/asn1/KyberPublicKey.cs
new file mode 100644
index 000000000..9f162e334
--- /dev/null
+++ b/crypto/src/pqc/asn1/KyberPublicKey.cs
@@ -0,0 +1,60 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Pqc.Asn1
+{
+    /**
+     *    Crystal Kyber Public Key Format.
+     *    See https://www.ietf.org/archive/id/draft-uni-qsckeys-kyber-00.html for details.
+     *    <pre>
+     *        KyberPublicKey ::= SEQUENCE {
+     *         t           OCTET STRING,
+     *         rho         OCTET STRING
+     *     }
+     *    </pre>
+     */
+    [Obsolete("Will be removed as this draft proposal was rejected")]
+    public sealed class KyberPublicKey
+        : Asn1Encodable
+    {
+        public static KyberPublicKey GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is KyberPublicKey kyberPublicKey)
+                return kyberPublicKey;
+            return new KyberPublicKey(Asn1Sequence.GetInstance(obj));
+        }
+
+        public static KyberPublicKey GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
+        private readonly byte[] m_t;
+        private readonly byte[] m_rho;
+
+        public KyberPublicKey(byte[] t, byte[] rho)
+        {
+            m_t = t;
+            m_rho = rho;
+        }
+
+        private KyberPublicKey(Asn1Sequence seq)
+        {
+            m_t = Arrays.Clone(Asn1OctetString.GetInstance(seq[0]).GetOctets());
+            m_rho = Arrays.Clone(Asn1OctetString.GetInstance(seq[1]).GetOctets());
+        }
+
+        public byte[] T => Arrays.Clone(m_t);
+
+        public byte[] Rho => Arrays.Clone(m_rho);
+
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(new DerOctetString(m_t), new DerOctetString(m_rho));
+        }
+    }
+}
diff --git a/crypto/src/pqc/crypto/utils/PqcPublicKeyFactory.cs b/crypto/src/pqc/crypto/utils/PqcPublicKeyFactory.cs
index 3c9849799..909b93577 100644
--- a/crypto/src/pqc/crypto/utils/PqcPublicKeyFactory.cs
+++ b/crypto/src/pqc/crypto/utils/PqcPublicKeyFactory.cs
@@ -21,6 +21,7 @@ using Org.BouncyCastle.Pqc.Crypto.Saber;
 using Org.BouncyCastle.Pqc.Crypto.Sike;
 using Org.BouncyCastle.Pqc.Crypto.SphincsPlus;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
 
 namespace Org.BouncyCastle.Pqc.Crypto.Utilities
 {
@@ -153,18 +154,15 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
         /// <exception cref="IOException"> on an error decoding the key</exception>
         public static AsymmetricKeyParameter CreateKey(SubjectPublicKeyInfo keyInfo, object defaultParams)
         {
-            AlgorithmIdentifier algId = keyInfo.AlgorithmID;
-            SubjectPublicKeyInfoConverter converter = (SubjectPublicKeyInfoConverter)Converters[algId.Algorithm];
+            var algID = keyInfo.AlgorithmID;
+            var oid = algID.Algorithm;
 
-            if (converter != null)
-            {
-                return converter.GetPublicKeyParameters(keyInfo, defaultParams);
-            }
-            else
-            {
-                throw new IOException("algorithm identifier in public key not recognised: " + algId.Algorithm);
-            }
+            SubjectPublicKeyInfoConverter converter = CollectionUtilities.GetValueOrNull(Converters, oid)
+                ?? throw new IOException("algorithm identifier in public key not recognised: " + oid);
+
+            return converter.GetPublicKeyParameters(keyInfo, defaultParams);
         }
+
         private abstract class SubjectPublicKeyInfoConverter
         {
             internal abstract AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, object defaultParams);
@@ -294,24 +292,24 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
         private class KyberConverter
             : SubjectPublicKeyInfoConverter
         {
-            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, object defaultParams)
+            internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo,
+                object defaultParams)
             {
                 KyberParameters kyberParameters = PqcUtilities.KyberParamsLookup(keyInfo.AlgorithmID.Algorithm);
 
-                Asn1Object obj = keyInfo.ParsePublicKey();
-                if (obj is Asn1Sequence)
+                try
                 {
-                    Asn1Sequence keySeq = Asn1Sequence.GetInstance(obj);
+                    Asn1Object obj = keyInfo.ParsePublicKey();
+#pragma warning disable CS0618 // Type or member is obsolete
+                    KyberPublicKey kyberKey = KyberPublicKey.GetInstance(obj);
+#pragma warning restore CS0618 // Type or member is obsolete
 
-                    return new KyberPublicKeyParameters(kyberParameters,
-                        Asn1OctetString.GetInstance(keySeq[0]).GetOctets(),
-                        Asn1OctetString.GetInstance(keySeq[1]).GetOctets());
+                    return new KyberPublicKeyParameters(kyberParameters, kyberKey.T, kyberKey.Rho);
                 }
-                else
+                catch (Exception)
                 {
-                    byte[] encKey = Asn1OctetString.GetInstance(obj).GetOctets();
-
-                    return new KyberPublicKeyParameters(kyberParameters, encKey);
+                    // we're a raw encoding
+                    return new KyberPublicKeyParameters(kyberParameters, keyInfo.PublicKeyData.GetOctets());
                 }
             }
         }
diff --git a/crypto/src/pqc/crypto/utils/PqcSubjectPublicKeyInfoFactory.cs b/crypto/src/pqc/crypto/utils/PqcSubjectPublicKeyInfoFactory.cs
index 672108789..c13255c68 100644
--- a/crypto/src/pqc/crypto/utils/PqcSubjectPublicKeyInfoFactory.cs
+++ b/crypto/src/pqc/crypto/utils/PqcSubjectPublicKeyInfoFactory.cs
@@ -115,10 +115,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities
             {
                 AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(
                     PqcUtilities.KyberOidLookup(kyberPublicKeyParameters.Parameters));
-                Asn1EncodableVector v = new Asn1EncodableVector(2);
-                v.Add(new DerOctetString(kyberPublicKeyParameters.T));
-                v.Add(new DerOctetString(kyberPublicKeyParameters.Rho));
-                return new SubjectPublicKeyInfo(algorithmIdentifier, new DerSequence(v));
+
+                return new SubjectPublicKeyInfo(algorithmIdentifier, kyberPublicKeyParameters.GetEncoded());
             }
             if (publicKey is DilithiumPublicKeyParameters dilithiumPublicKeyParameters)
             {