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)
{
|