summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2023-02-18 15:15:10 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2023-02-18 15:15:10 +0700
commit7a79336a216eb2b3851f63647a3ba6c708259b99 (patch)
treeffd1285505f801d0672c36d098e4cb4bd4567d50
parentGCM perf. opts. (diff)
downloadBouncyCastle.NET-ed25519-7a79336a216eb2b3851f63647a3ba6c708259b99.tar.xz
ASN.1: "Alternative algorithm" types and extension OIDs
-rw-r--r--crypto/src/asn1/x509/AlgorithmIdentifier.cs19
-rw-r--r--crypto/src/asn1/x509/AltSignatureAlgorithm.cs70
-rw-r--r--crypto/src/asn1/x509/AltSignatureValue.cs70
-rw-r--r--crypto/src/asn1/x509/SubjectAltPublicKeyInfo.cs84
-rw-r--r--crypto/src/asn1/x509/X509Extensions.cs15
-rw-r--r--crypto/test/src/asn1/test/X509AltTest.cs44
6 files changed, 291 insertions, 11 deletions
diff --git a/crypto/src/asn1/x509/AlgorithmIdentifier.cs b/crypto/src/asn1/x509/AlgorithmIdentifier.cs
index 169a95c0a..486772c16 100644
--- a/crypto/src/asn1/x509/AlgorithmIdentifier.cs
+++ b/crypto/src/asn1/x509/AlgorithmIdentifier.cs
@@ -8,23 +8,20 @@ namespace Org.BouncyCastle.Asn1.X509
         private readonly DerObjectIdentifier	algorithm;
         private readonly Asn1Encodable			parameters;
 
-        public static AlgorithmIdentifier GetInstance(
-            Asn1TaggedObject	obj,
-            bool				explicitly)
-        {
-            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
-        }
-
-        public static AlgorithmIdentifier GetInstance(
-            object obj)
+        public static AlgorithmIdentifier GetInstance(object obj)
         {
             if (obj == null)
                 return null;
-            if (obj is AlgorithmIdentifier)
-                return (AlgorithmIdentifier)obj;
+            if (obj is AlgorithmIdentifier algorithmIdentifier)
+                return algorithmIdentifier;
             return new AlgorithmIdentifier(Asn1Sequence.GetInstance(obj));
         }
 
+        public static AlgorithmIdentifier GetInstance(Asn1TaggedObject obj, bool explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
         public AlgorithmIdentifier(
             DerObjectIdentifier algorithm)
         {
diff --git a/crypto/src/asn1/x509/AltSignatureAlgorithm.cs b/crypto/src/asn1/x509/AltSignatureAlgorithm.cs
new file mode 100644
index 000000000..0844de324
--- /dev/null
+++ b/crypto/src/asn1/x509/AltSignatureAlgorithm.cs
@@ -0,0 +1,70 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * X.509 Section 9.8.3.
+     * <br/>
+     * This extension may be used as a public-key certificate extension, a CRL extension or an AVL extension. It shall contain
+     * the algorithm identifier for the alternative digital signature algorithm used by the signer when creating an alternative
+     * digital signature and by the relying party when validating the alternative digital signature.
+     * <pre>
+     * altSignatureAlgorithm EXTENSION ::= {
+     *     SYNTAX AltSignatureAlgorithm
+     *     IDENTIFIED BY id-ce-altSignatureAlgorithm }
+     *
+     * AltSignatureAlgorithm ::= AlgorithmIdentifier{{SupportedAlgorithms}}
+     * </pre>
+     * When the altSignatureAlgorithm extension is included in a particular value that is an instance of a data type that
+     * supports extensions, the altSignatureValue extension shall also be included.
+     * <br/>
+     * NOTE 1 – By having a separate altSignatureAlgorithm extension, instead of having it combined with the
+     * altSignatureValue extension, the alternative digital signature algorithm is protected by the alternative signature.
+     * This extension may be flagged either as critical or as non-critical.
+     * <br/>
+     * NOTE 2 – It is recommended that it be flagged as non-critical. Flagging it as critical would require all relying parties to understand
+     * the extension and the alternative public-key algorithms
+     */
+    public class AltSignatureAlgorithm
+        : Asn1Encodable
+    {
+        private readonly AlgorithmIdentifier m_algorithm;
+
+        public static AltSignatureAlgorithm GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is AltSignatureAlgorithm altSignatureAlgorithm)
+                return altSignatureAlgorithm;
+            return new AltSignatureAlgorithm(AlgorithmIdentifier.GetInstance(obj));
+        }
+
+        public static AltSignatureAlgorithm GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(AlgorithmIdentifier.GetInstance(taggedObject, declaredExplicit));
+        }
+
+        public static AltSignatureAlgorithm FromExtensions(X509Extensions extensions)
+        {
+            return GetInstance(
+                X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.AltSignatureAlgorithm));
+        }
+
+        public AltSignatureAlgorithm(AlgorithmIdentifier algorithm)
+        {
+            m_algorithm = algorithm;
+        }
+
+        public AltSignatureAlgorithm(DerObjectIdentifier algorithm, Asn1Encodable parameters)
+        {
+            m_algorithm = new AlgorithmIdentifier(algorithm, parameters);
+        }
+
+        public AlgorithmIdentifier Algorithm => m_algorithm;
+
+        public override Asn1Object ToAsn1Object()
+        {
+            return m_algorithm.ToAsn1Object();
+        }
+    }
+}
diff --git a/crypto/src/asn1/x509/AltSignatureValue.cs b/crypto/src/asn1/x509/AltSignatureValue.cs
new file mode 100644
index 000000000..498c1d6d0
--- /dev/null
+++ b/crypto/src/asn1/x509/AltSignatureValue.cs
@@ -0,0 +1,70 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * X.509 Section 9.8.4.
+     * <br/>
+     * This extension may be used as a public-key certificate extension, a CRL extension or an AVL extension.
+     * This alternative signature shall be created by the issuer using its alternative private key, and it shall be verified using the
+     * alternative public key of the issuer.
+     * <pre>
+     * altSignatureValue EXTENSION ::= {
+     *     SYNTAX AltSignatureValue
+     *     IDENTIFIED BY id-ce-altSignatureValue }
+     *
+     * AltSignatureValue ::= BIT STRING
+     * </pre>
+     * This extension can only be created by a signer holding a multiple cryptographic algorithms public-key certificate. When
+     * creating the alternative digital signature on an issued public-key certificate or CRL, the signer shall use its alternative
+     * private key.
+     * <br/>
+     * The procedures for creating and validating alternative digital signatures are specified in:
+     * <ul>
+     * <li>clause 7.2.2 for public-key certificates;</li>
+     * <li>clause 7.10.3 for CRLs: and</li>
+     * <li>clause 11.4 for AVLs.</li>
+     * </ul>
+     */
+    public class AltSignatureValue
+        : Asn1Encodable
+    {
+        private readonly DerBitString m_signature;
+
+        public static AltSignatureValue GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is AltSignatureValue altSignatureValue)
+                return altSignatureValue;
+            return new AltSignatureValue(DerBitString.GetInstance(obj));
+        }
+
+        public static AltSignatureValue GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(DerBitString.GetInstance(taggedObject, declaredExplicit));
+        }
+
+        public static AltSignatureValue FromExtensions(X509Extensions extensions)
+        {
+            return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.AltSignatureValue));
+        }
+
+        private AltSignatureValue(DerBitString signature)
+        {
+            m_signature = signature;
+        }
+
+        public AltSignatureValue(byte[] signature)
+        {
+            m_signature = new DerBitString(signature);
+        }
+
+        public DerBitString Signature => m_signature;
+
+        public override Asn1Object ToAsn1Object()
+        {
+            return m_signature;
+        }
+    }
+}
diff --git a/crypto/src/asn1/x509/SubjectAltPublicKeyInfo.cs b/crypto/src/asn1/x509/SubjectAltPublicKeyInfo.cs
new file mode 100644
index 000000000..4fe165898
--- /dev/null
+++ b/crypto/src/asn1/x509/SubjectAltPublicKeyInfo.cs
@@ -0,0 +1,84 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * X.509 Section 9.8.2.
+     * <br/>
+     * This public-key certificate extension, when present, shall contain the subject’s alternative public key information
+     * <pre>
+     * subjectAltPublicKeyInfo EXTENSION ::= {
+     *      SYNTAX SubjectAltPublicKeyInfo
+     *      IDENTIFIED BY id-ce-subjectAltPublicKeyInfo }
+     *
+     * SubjectAltPublicKeyInfo ::= SEQUENCE {
+     *     algorithm AlgorithmIdentifier{{SupportedAlgorithms}},
+     *     subjectAltPublicKey BIT STRING }
+     * </pre>
+     * The SubjectAltPublicKeyInfo data type has the following components:
+     * <ul>
+     * <li>the algorithm subcomponent, which shall hold the algorithm that this public key is an instance of</li>
+     * <li>the subjectAltPublicKey subcomponent, which shall hold the alternative public key</li>
+     * </ul>
+     * This extension may be flagged as critical or as non-critical.
+     * <br/>
+     * NOTE – It is recommended that it be flagged as non-critical. Flagging it as critical would require relying parties to understand this
+     * extension and the alternative public-key algorithm.
+     */
+    public class SubjectAltPublicKeyInfo
+        : Asn1Encodable
+    {
+        private readonly AlgorithmIdentifier m_algorithm;
+        private readonly DerBitString m_subjectAltPublicKey;
+
+        public static SubjectAltPublicKeyInfo GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is SubjectAltPublicKeyInfo subjectAltPublicKeyInfo)
+                return subjectAltPublicKeyInfo;
+            return new SubjectAltPublicKeyInfo(Asn1Sequence.GetInstance(obj));
+        }
+
+        public static SubjectAltPublicKeyInfo GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
+        public static SubjectAltPublicKeyInfo FromExtensions(X509Extensions extensions)
+        {
+            return GetInstance(
+                X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.SubjectAltPublicKeyInfo));
+        }
+
+        private SubjectAltPublicKeyInfo(Asn1Sequence seq)
+        {
+            if (seq.Count != 2)
+                throw new ArgumentException("extension should contain only 2 elements");
+
+            m_algorithm = AlgorithmIdentifier.GetInstance(seq[0]);
+            m_subjectAltPublicKey = DerBitString.GetInstance(seq[1]);
+        }
+
+        public SubjectAltPublicKeyInfo(AlgorithmIdentifier algorithm, DerBitString subjectAltPublicKey)
+        {
+            m_algorithm = algorithm;
+            m_subjectAltPublicKey = subjectAltPublicKey;
+        }
+
+        public SubjectAltPublicKeyInfo(SubjectPublicKeyInfo subjectPublicKeyInfo)
+        {
+            m_algorithm = subjectPublicKeyInfo.AlgorithmID;
+            m_subjectAltPublicKey = subjectPublicKeyInfo.PublicKeyData;
+        }
+
+        public AlgorithmIdentifier Algorithm => Algorithm;
+
+        public DerBitString SubjectAltPublicKey => m_subjectAltPublicKey;
+
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(m_algorithm, m_subjectAltPublicKey);
+        }
+    }
+}
diff --git a/crypto/src/asn1/x509/X509Extensions.cs b/crypto/src/asn1/x509/X509Extensions.cs
index aa5205800..62291a829 100644
--- a/crypto/src/asn1/x509/X509Extensions.cs
+++ b/crypto/src/asn1/x509/X509Extensions.cs
@@ -169,6 +169,21 @@ namespace Org.BouncyCastle.Asn1.X509
          */
         public static readonly DerObjectIdentifier ExpiredCertsOnCrl = new DerObjectIdentifier("2.5.29.60");
 
+        /**
+         * the subject’s alternative public key information
+         */
+        public static readonly DerObjectIdentifier SubjectAltPublicKeyInfo = new DerObjectIdentifier("2.5.29.72");
+
+        /**
+         * the algorithm identifier for the alternative digital signature algorithm.
+         */
+        public static readonly DerObjectIdentifier AltSignatureAlgorithm = new DerObjectIdentifier("2.5.29.73");
+
+        /**
+         * alternative signature shall be created by the issuer using its alternative private key.
+         */
+        public static readonly DerObjectIdentifier AltSignatureValue = new DerObjectIdentifier("2.5.29.74");
+
         private readonly Dictionary<DerObjectIdentifier, X509Extension> m_extensions =
             new Dictionary<DerObjectIdentifier, X509Extension>();
         private readonly List<DerObjectIdentifier> m_ordering;
diff --git a/crypto/test/src/asn1/test/X509AltTest.cs b/crypto/test/src/asn1/test/X509AltTest.cs
new file mode 100644
index 000000000..047d2e23b
--- /dev/null
+++ b/crypto/test/src/asn1/test/X509AltTest.cs
@@ -0,0 +1,44 @@
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class X509AltTest
+    {
+        [Test]
+        public void TestX509AltTypes()
+        {
+            SubjectAltPublicKeyInfo subAlt = new SubjectAltPublicKeyInfo(
+                new AlgorithmIdentifier(PkcsObjectIdentifiers.RsaEncryption, DerNull.Instance),
+                new DerBitString(Hex.DecodeStrict("0102030405060708090807060504030201")));
+            AltSignatureValue sigValAlt = new AltSignatureValue(Hex.DecodeStrict("0102030405060708090807060504030201"));
+
+            AltSignatureAlgorithm sigAlgAlt = new AltSignatureAlgorithm(
+                new AlgorithmIdentifier(PkcsObjectIdentifiers.MD5WithRsaEncryption, DerNull.Instance));
+            AltSignatureAlgorithm sigAlgAlt2 = new AltSignatureAlgorithm(
+                PkcsObjectIdentifiers.MD5WithRsaEncryption, DerNull.Instance);
+
+            Assert.AreEqual(sigAlgAlt, sigAlgAlt2);
+
+            var extGen = new X509ExtensionsGenerator();
+            extGen.AddExtension(X509Extensions.SubjectAltPublicKeyInfo, false, subAlt);
+            extGen.AddExtension(X509Extensions.AltSignatureAlgorithm, false, sigAlgAlt);
+            extGen.AddExtension(X509Extensions.AltSignatureValue, false, sigValAlt);
+
+            var exts = extGen.Generate();
+            Assert.AreEqual(subAlt, SubjectAltPublicKeyInfo.FromExtensions(exts));
+            Assert.AreEqual(sigAlgAlt, AltSignatureAlgorithm.FromExtensions(exts));
+            Assert.AreEqual(sigValAlt, AltSignatureValue.FromExtensions(exts));
+            Assert.AreEqual(subAlt, SubjectAltPublicKeyInfo.GetInstance(subAlt.GetEncoded()));
+            Assert.AreEqual(sigAlgAlt, AltSignatureAlgorithm.GetInstance(sigAlgAlt.GetEncoded()));
+            Assert.AreEqual(sigValAlt, AltSignatureValue.GetInstance(sigValAlt.GetEncoded()));
+            Assert.AreEqual(subAlt, SubjectAltPublicKeyInfo.GetInstance(new DerTaggedObject(1, subAlt), true));
+            Assert.AreEqual(sigAlgAlt, AltSignatureAlgorithm.GetInstance(new DerTaggedObject(1, sigAlgAlt), true));
+            Assert.AreEqual(sigValAlt, AltSignatureValue.GetInstance(new DerTaggedObject(1, sigValAlt), true));
+        }
+    }
+}