summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2024-06-24 20:04:26 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2024-06-24 20:04:26 +0700
commit438dc8d53aac9b7483a2014cd4398b8275c496ab (patch)
treed4e53f01313d43c20cf32ae5c930e0d54a364114
parentAdd TODO (diff)
downloadBouncyCastle.NET-ed25519-438dc8d53aac9b7483a2014cd4398b8275c496ab.tar.xz
ASN.1: Use GetTagged with cursor methods
- Add GetTagged method for all CHOICE types
- Make most Asn1Utilities methods public
-rw-r--r--crypto/src/asn1/Asn1Utilities.cs47
-rw-r--r--crypto/src/asn1/bc/LinkedCertificate.cs4
-rw-r--r--crypto/src/asn1/cmp/CertAnnContent.cs9
-rw-r--r--crypto/src/asn1/cmp/CertOrEncCert.cs9
-rw-r--r--crypto/src/asn1/cmp/CertRepMessage.cs2
-rw-r--r--crypto/src/asn1/cmp/CertStatus.cs2
-rw-r--r--crypto/src/asn1/cmp/CertifiedKeyPair.cs4
-rw-r--r--crypto/src/asn1/cmp/CmpCertificate.cs9
-rw-r--r--crypto/src/asn1/cmp/CrlSource.cs9
-rw-r--r--crypto/src/asn1/cmp/KemOtherInfo.cs6
-rw-r--r--crypto/src/asn1/cmp/KeyRecRepContent.cs6
-rw-r--r--crypto/src/asn1/cmp/OobCert.cs9
-rw-r--r--crypto/src/asn1/cmp/OobCertHash.cs4
-rw-r--r--crypto/src/asn1/cmp/PKIBody.cs9
-rw-r--r--crypto/src/asn1/cmp/PKIFreeText.cs9
-rw-r--r--crypto/src/asn1/cmp/PKIHeader.cs18
-rw-r--r--crypto/src/asn1/cmp/PKIMessage.cs4
-rw-r--r--crypto/src/asn1/cmp/RevRepContent.cs4
-rw-r--r--crypto/src/asn1/cmp/RootCaKeyUpdateContent.cs4
-rw-r--r--crypto/src/asn1/cms/AuthEnvelopedData.cs6
-rw-r--r--crypto/src/asn1/cms/AuthenticatedData.cs8
-rw-r--r--crypto/src/asn1/cms/CmsAlgorithmProtection.cs4
-rw-r--r--crypto/src/asn1/cms/ContentInfo.cs9
-rw-r--r--crypto/src/asn1/cms/EncryptedContentInfo.cs2
-rw-r--r--crypto/src/asn1/cms/EncryptedData.cs2
-rw-r--r--crypto/src/asn1/cms/EnvelopedData.cs4
-rw-r--r--crypto/src/asn1/cms/Evidence.cs9
-rw-r--r--crypto/src/asn1/cms/KemRecipientInfo.cs2
-rw-r--r--crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs9
-rw-r--r--crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs4
-rw-r--r--crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs9
-rw-r--r--crypto/src/asn1/cms/OriginatorInfo.cs11
-rw-r--r--crypto/src/asn1/cms/PasswordRecipientInfo.cs2
-rw-r--r--crypto/src/asn1/cms/RecipientIdentifier.cs9
-rw-r--r--crypto/src/asn1/cms/RecipientInfo.cs9
-rw-r--r--crypto/src/asn1/cms/SCVPReqRes.cs2
-rw-r--r--crypto/src/asn1/cms/SignerIdentifier.cs9
-rw-r--r--crypto/src/asn1/cms/SignerInfo.cs4
-rw-r--r--crypto/src/asn1/cms/Time.cs9
-rw-r--r--crypto/src/asn1/cms/ecc/MQVuserKeyingMaterial.cs2
-rw-r--r--crypto/src/asn1/crmf/CertId.cs9
-rw-r--r--crypto/src/asn1/crmf/CertTemplate.cs20
-rw-r--r--crypto/src/asn1/crmf/EncryptedKey.cs9
-rw-r--r--crypto/src/asn1/crmf/OptionalValidity.cs13
-rw-r--r--crypto/src/asn1/crmf/PKIArchiveOptions.cs9
-rw-r--r--crypto/src/asn1/crmf/PKIPublicationInfo.cs9
-rw-r--r--crypto/src/asn1/crmf/PopoPrivKey.cs9
-rw-r--r--crypto/src/asn1/crmf/PopoSigningKey.cs2
-rw-r--r--crypto/src/asn1/crmf/PopoSigningKeyInput.cs9
-rw-r--r--crypto/src/asn1/crmf/ProofOfPossession.cs9
-rw-r--r--crypto/src/asn1/esf/CrlListID.cs9
-rw-r--r--crypto/src/asn1/esf/CrlOcspRef.cs6
-rw-r--r--crypto/src/asn1/esf/OcspListID.cs9
-rw-r--r--crypto/src/asn1/esf/OtherHash.cs9
-rw-r--r--crypto/src/asn1/esf/OtherRevRefs.cs9
-rw-r--r--crypto/src/asn1/esf/OtherRevVals.cs9
-rw-r--r--crypto/src/asn1/esf/RevocationValues.cs6
-rw-r--r--crypto/src/asn1/esf/SignaturePolicyIdentifier.cs9
-rw-r--r--crypto/src/asn1/esf/SignerLocation.cs6
-rw-r--r--crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs9
-rw-r--r--crypto/src/asn1/ocsp/BasicOCSPResponse.cs2
-rw-r--r--crypto/src/asn1/ocsp/CertStatus.cs9
-rw-r--r--crypto/src/asn1/ocsp/CrlID.cs6
-rw-r--r--crypto/src/asn1/ocsp/OCSPRequest.cs2
-rw-r--r--crypto/src/asn1/ocsp/OCSPResponse.cs2
-rw-r--r--crypto/src/asn1/ocsp/Request.cs2
-rw-r--r--crypto/src/asn1/ocsp/ResponderID.cs9
-rw-r--r--crypto/src/asn1/ocsp/ResponseBytes.cs9
-rw-r--r--crypto/src/asn1/ocsp/ResponseData.cs4
-rw-r--r--crypto/src/asn1/ocsp/RevokedInfo.cs2
-rw-r--r--crypto/src/asn1/ocsp/Signature.cs11
-rw-r--r--crypto/src/asn1/ocsp/SingleResponse.cs4
-rw-r--r--crypto/src/asn1/ocsp/TBSRequest.cs6
-rw-r--r--crypto/src/asn1/pkcs/CertificationRequestInfo.cs2
-rw-r--r--crypto/src/asn1/pkcs/PrivateKeyInfo.cs24
-rw-r--r--crypto/src/asn1/pkcs/RSAESOAEPparams.cs6
-rw-r--r--crypto/src/asn1/pkcs/RSASSAPSSparams.cs8
-rw-r--r--crypto/src/asn1/pkcs/SignedData.cs4
-rw-r--r--crypto/src/asn1/pkcs/SignerInfo.cs4
-rw-r--r--crypto/src/asn1/x500/DirectoryString.cs11
-rw-r--r--crypto/src/asn1/x509/AlgorithmIdentifier.cs9
-rw-r--r--crypto/src/asn1/x509/AttCertIssuer.cs21
-rw-r--r--crypto/src/asn1/x509/DisplayText.cs9
-rw-r--r--crypto/src/asn1/x509/DistributionPointName.cs9
-rw-r--r--crypto/src/asn1/x509/GeneralName.cs9
-rw-r--r--crypto/src/asn1/x509/GeneralNames.cs9
-rw-r--r--crypto/src/asn1/x509/SubjectPublicKeyInfo.cs20
-rw-r--r--crypto/src/asn1/x509/Time.cs9
-rw-r--r--crypto/src/asn1/x509/X509Extensions.cs11
-rw-r--r--crypto/src/asn1/x509/X509Name.cs3
-rw-r--r--crypto/src/asn1/x9/X962Parameters.cs11
91 files changed, 414 insertions, 305 deletions
diff --git a/crypto/src/asn1/Asn1Utilities.cs b/crypto/src/asn1/Asn1Utilities.cs
index c3449c050..9e42ad5c2 100644
--- a/crypto/src/asn1/Asn1Utilities.cs
+++ b/crypto/src/asn1/Asn1Utilities.cs
@@ -8,27 +8,27 @@ namespace Org.BouncyCastle.Asn1
     // TODO[api] Make static
     public abstract class Asn1Utilities
     {
-        internal static Asn1TaggedObject CheckContextTag(Asn1TaggedObject taggedObject, int tagNo)
+        public static Asn1TaggedObject CheckContextTag(Asn1TaggedObject taggedObject, int tagNo)
         {
             return CheckTag(taggedObject, Asn1Tags.ContextSpecific, tagNo);
         }
 
-        internal static Asn1TaggedObjectParser CheckContextTag(Asn1TaggedObjectParser taggedObjectParser, int tagNo)
+        public static Asn1TaggedObjectParser CheckContextTag(Asn1TaggedObjectParser taggedObjectParser, int tagNo)
         {
             return CheckTag(taggedObjectParser, Asn1Tags.ContextSpecific, tagNo);
         }
 
-        internal static Asn1TaggedObject CheckContextTagClass(Asn1TaggedObject taggedObject)
+        public static Asn1TaggedObject CheckContextTagClass(Asn1TaggedObject taggedObject)
         {
             return CheckTagClass(taggedObject, Asn1Tags.ContextSpecific);
         }
 
-        internal static Asn1TaggedObjectParser CheckContextTagClass(Asn1TaggedObjectParser taggedObjectParser)
+        public static Asn1TaggedObjectParser CheckContextTagClass(Asn1TaggedObjectParser taggedObjectParser)
         {
             return CheckTagClass(taggedObjectParser, Asn1Tags.ContextSpecific);
         }
 
-        internal static Asn1TaggedObject CheckTag(Asn1TaggedObject taggedObject, int tagClass, int tagNo)
+        public static Asn1TaggedObject CheckTag(Asn1TaggedObject taggedObject, int tagClass, int tagNo)
         {
             if (!taggedObject.HasTag(tagClass, tagNo))
             {
@@ -39,7 +39,7 @@ namespace Org.BouncyCastle.Asn1
             return taggedObject;
         }
 
-        internal static Asn1TaggedObjectParser CheckTag(Asn1TaggedObjectParser taggedObjectParser, int tagClass,
+        public static Asn1TaggedObjectParser CheckTag(Asn1TaggedObjectParser taggedObjectParser, int tagClass,
             int tagNo)
         {
             if (!taggedObjectParser.HasTag(tagClass, tagNo))
@@ -51,7 +51,7 @@ namespace Org.BouncyCastle.Asn1
             return taggedObjectParser;
         }
 
-        internal static Asn1TaggedObject CheckTagClass(Asn1TaggedObject taggedObject, int tagClass)
+        public static Asn1TaggedObject CheckTagClass(Asn1TaggedObject taggedObject, int tagClass)
         {
             if (!taggedObject.HasTagClass(tagClass))
             {
@@ -62,7 +62,7 @@ namespace Org.BouncyCastle.Asn1
             return taggedObject;
         }
 
-        internal static Asn1TaggedObjectParser CheckTagClass(Asn1TaggedObjectParser taggedObjectParser, int tagClass)
+        public static Asn1TaggedObjectParser CheckTagClass(Asn1TaggedObjectParser taggedObjectParser, int tagClass)
         {
             if (taggedObjectParser.TagClass != tagClass)
             {
@@ -73,8 +73,26 @@ namespace Org.BouncyCastle.Asn1
             return taggedObjectParser;
         }
 
-        internal static TChoice GetInstanceFromChoice<TChoice>(Asn1TaggedObject taggedObject, bool declaredExplicit,
-            Func<object, TChoice> constructor)
+        public static TChoice GetInstanceChoice<TChoice>(Asn1TaggedObject taggedObject, bool declaredExplicit,
+            Func<Asn1Encodable, TChoice> constructor)
+            where TChoice : Asn1Encodable, IAsn1Choice
+        {
+            if (!declaredExplicit)
+            {
+                var message = string.Format(
+                    "Implicit tagging cannot be used with untagged choice type {0} (X.680 30.6, 30.8).",
+                    Platform.GetTypeName(typeof(TChoice)));
+
+                throw new ArgumentException(message, nameof(declaredExplicit));
+            }
+            if (taggedObject == null)
+                throw new ArgumentNullException(nameof(taggedObject));
+
+            return constructor(CheckContextTagClass(taggedObject).GetExplicitBaseObject());
+        }
+
+        public static TChoice GetTaggedChoice<TChoice>(Asn1TaggedObject taggedObject, bool declaredExplicit,
+            Func<Asn1Encodable, TChoice> constructor)
             where TChoice : Asn1Encodable, IAsn1Choice
         {
             if (!declaredExplicit)
@@ -121,8 +139,10 @@ namespace Org.BouncyCastle.Asn1
                 return "CONTEXT";
             case Asn1Tags.Private:
                 return "PRIVATE";
-            default:
+            case Asn1Tags.Universal:
                 return "UNIVERSAL";
+            default:
+                return string.Format("UNKNOWN({0})", tagClass);
             }
         }
 
@@ -151,8 +171,10 @@ namespace Org.BouncyCastle.Asn1
                 return string.Format("[CONTEXT {0}]", tagNo);
             case Asn1Tags.Private:
                 return string.Format("[PRIVATE {0}]", tagNo);
-            default:
+            case Asn1Tags.Universal:
                 return string.Format("[UNIVERSAL {0}]", tagNo);
+            default:
+                return string.Format("[UNKNOWN({0}) {1}]", tagClass, tagNo);
             }
         }
 
@@ -650,6 +672,7 @@ namespace Org.BouncyCastle.Asn1
             return TryParseExplicitBaseObject(taggedObjectParser, Asn1Tags.ContextSpecific, tagNo, out baseObject);
         }
 
+
         #region Sequence cursor
 
         public static TResult ReadContextTagged<TState, TResult>(Asn1Sequence sequence, ref int sequencePosition,
diff --git a/crypto/src/asn1/bc/LinkedCertificate.cs b/crypto/src/asn1/bc/LinkedCertificate.cs
index e530cd82c..2601d870b 100644
--- a/crypto/src/asn1/bc/LinkedCertificate.cs
+++ b/crypto/src/asn1/bc/LinkedCertificate.cs
@@ -60,8 +60,8 @@ namespace Org.BouncyCastle.Asn1.BC
 
             m_digest = DigestInfo.GetInstance(seq[pos++]);
             m_certLocation = GeneralName.GetInstance(seq[pos++]);
-            m_certIssuer = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, X509Name.GetInstance);
-            m_cACerts = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, GeneralNames.GetInstance);
+            m_certIssuer = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, X509Name.GetTagged);
+            m_cACerts = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, GeneralNames.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/cmp/CertAnnContent.cs b/crypto/src/asn1/cmp/CertAnnContent.cs
index d41f48e2e..1a0506132 100644
--- a/crypto/src/asn1/cmp/CertAnnContent.cs
+++ b/crypto/src/asn1/cmp/CertAnnContent.cs
@@ -23,10 +23,11 @@ namespace Org.BouncyCastle.Asn1.Cmp
             return new CertAnnContent(X509CertificateStructure.GetInstance(obj));
         }
 
-        public static new CertAnnContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static new CertAnnContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public static new CertAnnContent GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         [Obsolete("Use 'GetInstance' from tagged object instead")]
         public CertAnnContent(int type, Asn1Object otherCert)
diff --git a/crypto/src/asn1/cmp/CertOrEncCert.cs b/crypto/src/asn1/cmp/CertOrEncCert.cs
index 430c1fd4f..b834194eb 100644
--- a/crypto/src/asn1/cmp/CertOrEncCert.cs
+++ b/crypto/src/asn1/cmp/CertOrEncCert.cs
@@ -16,10 +16,11 @@ namespace Org.BouncyCastle.Asn1.Cmp
             return new CertOrEncCert(Asn1TaggedObject.GetInstance(obj, Asn1Tags.ContextSpecific));
         }
 
-        public static CertOrEncCert GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static CertOrEncCert GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public static CertOrEncCert GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         private readonly CmpCertificate m_certificate;
 		private readonly EncryptedKey m_encryptedCert;
diff --git a/crypto/src/asn1/cmp/CertRepMessage.cs b/crypto/src/asn1/cmp/CertRepMessage.cs
index 9e7fae2e2..0a8569331 100644
--- a/crypto/src/asn1/cmp/CertRepMessage.cs
+++ b/crypto/src/asn1/cmp/CertRepMessage.cs
@@ -28,7 +28,7 @@ namespace Org.BouncyCastle.Asn1.Cmp
             if (count < 1 || count > 2)
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-			m_caPubs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Asn1Sequence.GetInstance);
+			m_caPubs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Asn1Sequence.GetTagged);
 			m_response = Asn1Sequence.GetInstance(seq[pos++]);
 
 			if (pos != count)
diff --git a/crypto/src/asn1/cmp/CertStatus.cs b/crypto/src/asn1/cmp/CertStatus.cs
index 5002b8811..ea735bca1 100644
--- a/crypto/src/asn1/cmp/CertStatus.cs
+++ b/crypto/src/asn1/cmp/CertStatus.cs
@@ -36,7 +36,7 @@ namespace Org.BouncyCastle.Asn1.Cmp
             m_certHash = Asn1OctetString.GetInstance(seq[pos++]);
             m_certReqID = DerInteger.GetInstance(seq[pos++]);
             m_statusInfo = Asn1Utilities.ReadOptional(seq, ref pos, PkiStatusInfo.GetOptional);
-            m_hashAlg = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, AlgorithmIdentifier.GetInstance);
+            m_hashAlg = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, AlgorithmIdentifier.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/cmp/CertifiedKeyPair.cs b/crypto/src/asn1/cmp/CertifiedKeyPair.cs
index 61da1d37a..bd86b93a0 100644
--- a/crypto/src/asn1/cmp/CertifiedKeyPair.cs
+++ b/crypto/src/asn1/cmp/CertifiedKeyPair.cs
@@ -47,8 +47,8 @@ namespace Org.BouncyCastle.Asn1.Cmp
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
             m_certOrEncCert = CertOrEncCert.GetInstance(seq[pos++]);
-            m_privateKey = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, EncryptedKey.GetInstance);
-            m_publicationInfo = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, PkiPublicationInfo.GetInstance);
+            m_privateKey = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, EncryptedKey.GetTagged);
+            m_publicationInfo = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, PkiPublicationInfo.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/cmp/CmpCertificate.cs b/crypto/src/asn1/cmp/CmpCertificate.cs
index e30eccca4..b0f9d7a5f 100644
--- a/crypto/src/asn1/cmp/CmpCertificate.cs
+++ b/crypto/src/asn1/cmp/CmpCertificate.cs
@@ -34,10 +34,11 @@ namespace Org.BouncyCastle.Asn1.Cmp
             return new CmpCertificate(X509CertificateStructure.GetInstance(asn1Object ?? obj));
         }
 
-        public static CmpCertificate GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static CmpCertificate GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public static CmpCertificate GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         private readonly X509CertificateStructure m_x509v3PKCert;
 
diff --git a/crypto/src/asn1/cmp/CrlSource.cs b/crypto/src/asn1/cmp/CrlSource.cs
index 4b6b396d9..394064788 100644
--- a/crypto/src/asn1/cmp/CrlSource.cs
+++ b/crypto/src/asn1/cmp/CrlSource.cs
@@ -26,10 +26,11 @@ namespace Org.BouncyCastle.Asn1.Cmp
             return new CrlSource(Asn1TaggedObject.GetInstance(obj));
         }
 
-        public static CrlSource GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static CrlSource GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public static CrlSource GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         private readonly DistributionPointName m_dpn;
         private readonly GeneralNames m_issuer;
diff --git a/crypto/src/asn1/cmp/KemOtherInfo.cs b/crypto/src/asn1/cmp/KemOtherInfo.cs
index 7b46dd398..043b7ce66 100644
--- a/crypto/src/asn1/cmp/KemOtherInfo.cs
+++ b/crypto/src/asn1/cmp/KemOtherInfo.cs
@@ -70,9 +70,9 @@ namespace Org.BouncyCastle.Asn1.Cmp
             if (!DEFAULT_staticString.Equals(m_staticString))
                 throw new ArgumentException("staticString field should be " + DEFAULT_staticString);
 
-            m_transactionID = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1OctetString.GetInstance);
-            m_senderNonce = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Asn1OctetString.GetInstance);
-            m_recipNonce = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, Asn1OctetString.GetInstance);
+            m_transactionID = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1OctetString.GetTagged);
+            m_senderNonce = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Asn1OctetString.GetTagged);
+            m_recipNonce = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, Asn1OctetString.GetTagged);
             m_len = DerInteger.GetInstance(seq[pos++]);
             m_mac = AlgorithmIdentifier.GetInstance(seq[pos++]);
             m_ct = Asn1OctetString.GetInstance(seq[pos++]);
diff --git a/crypto/src/asn1/cmp/KeyRecRepContent.cs b/crypto/src/asn1/cmp/KeyRecRepContent.cs
index ec604f644..0dea05b22 100644
--- a/crypto/src/asn1/cmp/KeyRecRepContent.cs
+++ b/crypto/src/asn1/cmp/KeyRecRepContent.cs
@@ -31,9 +31,9 @@ namespace Org.BouncyCastle.Asn1.Cmp
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
             m_status = PkiStatusInfo.GetInstance(seq[pos++]);
-            m_newSigCert = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, CmpCertificate.GetInstance);
-            m_caCerts = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Asn1Sequence.GetInstance);
-            m_keyPairHist = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, Asn1Sequence.GetInstance);
+            m_newSigCert = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, CmpCertificate.GetTagged);
+            m_caCerts = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Asn1Sequence.GetTagged);
+            m_keyPairHist = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, Asn1Sequence.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/cmp/OobCert.cs b/crypto/src/asn1/cmp/OobCert.cs
index 6d60f6bb6..24658c9a1 100644
--- a/crypto/src/asn1/cmp/OobCert.cs
+++ b/crypto/src/asn1/cmp/OobCert.cs
@@ -23,10 +23,11 @@ namespace Org.BouncyCastle.Asn1.Cmp
             return new OobCert(X509CertificateStructure.GetInstance(obj));
         }
 
-        public static new OobCert GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static new OobCert GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public static new OobCert GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         [Obsolete("Use constructor from Asn1TaggedObject instead")]
         public OobCert(int type, Asn1Encodable otherCert)
diff --git a/crypto/src/asn1/cmp/OobCertHash.cs b/crypto/src/asn1/cmp/OobCertHash.cs
index f1531f309..0ef4b98a9 100644
--- a/crypto/src/asn1/cmp/OobCertHash.cs
+++ b/crypto/src/asn1/cmp/OobCertHash.cs
@@ -44,8 +44,8 @@ namespace Org.BouncyCastle.Asn1.Cmp
             if (count < 1 || count > 3)
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-			m_hashAlg = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, AlgorithmIdentifier.GetInstance);
-            m_certId = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, CertId.GetInstance);
+			m_hashAlg = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, AlgorithmIdentifier.GetTagged);
+            m_certId = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, CertId.GetTagged);
 			m_hashVal = DerBitString.GetInstance(seq[pos++]);
 
 			if (pos != count)
diff --git a/crypto/src/asn1/cmp/PKIBody.cs b/crypto/src/asn1/cmp/PKIBody.cs
index 19a1a03a1..0329093ce 100644
--- a/crypto/src/asn1/cmp/PKIBody.cs
+++ b/crypto/src/asn1/cmp/PKIBody.cs
@@ -76,10 +76,11 @@ namespace Org.BouncyCastle.Asn1.Cmp
             return new PkiBody(Asn1TaggedObject.GetInstance(obj));
         }
 
-        public static PkiBody GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static PkiBody GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public static PkiBody GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         private readonly int m_tagNo;
         private readonly Asn1Encodable m_body;
diff --git a/crypto/src/asn1/cmp/PKIFreeText.cs b/crypto/src/asn1/cmp/PKIFreeText.cs
index e2845c529..81f3e128c 100644
--- a/crypto/src/asn1/cmp/PKIFreeText.cs
+++ b/crypto/src/asn1/cmp/PKIFreeText.cs
@@ -14,10 +14,8 @@ namespace Org.BouncyCastle.Asn1.Cmp
             return new PkiFreeText(Asn1Sequence.GetInstance(obj));
 		}
 
-        public static PkiFreeText GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return new PkiFreeText(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
-        }
+        public static PkiFreeText GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new PkiFreeText(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
 
         public static PkiFreeText GetOptional(Asn1Encodable element)
         {
@@ -34,6 +32,9 @@ namespace Org.BouncyCastle.Asn1.Cmp
             return null;
         }
 
+        public static PkiFreeText GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new PkiFreeText(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
+
         private readonly Asn1Sequence m_strings;
 
         internal PkiFreeText(Asn1Sequence seq)
diff --git a/crypto/src/asn1/cmp/PKIHeader.cs b/crypto/src/asn1/cmp/PKIHeader.cs
index 71dc18e7d..3cdf3346c 100644
--- a/crypto/src/asn1/cmp/PKIHeader.cs
+++ b/crypto/src/asn1/cmp/PKIHeader.cs
@@ -51,15 +51,15 @@ namespace Org.BouncyCastle.Asn1.Cmp
             m_pvno = DerInteger.GetInstance(seq[pos++]);
             m_sender = GeneralName.GetInstance(seq[pos++]);
             m_recipient = GeneralName.GetInstance(seq[pos++]);
-            m_messageTime = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1GeneralizedTime.GetInstance);
-            m_protectionAlg = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, AlgorithmIdentifier.GetInstance);
-            m_senderKID = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, Asn1OctetString.GetInstance);
-            m_recipKID = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 3, true, Asn1OctetString.GetInstance);
-            m_transactionID = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 4, true, Asn1OctetString.GetInstance);
-            m_senderNonce = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 5, true, Asn1OctetString.GetInstance);
-            m_recipNonce = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 6, true, Asn1OctetString.GetInstance);
-            m_freeText = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 7, true, PkiFreeText.GetInstance);
-            m_generalInfo = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 8, true, Asn1Sequence.GetInstance);
+            m_messageTime = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1GeneralizedTime.GetTagged);
+            m_protectionAlg = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, AlgorithmIdentifier.GetTagged);
+            m_senderKID = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, Asn1OctetString.GetTagged);
+            m_recipKID = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 3, true, Asn1OctetString.GetTagged);
+            m_transactionID = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 4, true, Asn1OctetString.GetTagged);
+            m_senderNonce = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 5, true, Asn1OctetString.GetTagged);
+            m_recipNonce = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 6, true, Asn1OctetString.GetTagged);
+            m_freeText = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 7, true, PkiFreeText.GetTagged);
+            m_generalInfo = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 8, true, Asn1Sequence.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/cmp/PKIMessage.cs b/crypto/src/asn1/cmp/PKIMessage.cs
index 4b5acad77..7008a9e1c 100644
--- a/crypto/src/asn1/cmp/PKIMessage.cs
+++ b/crypto/src/asn1/cmp/PKIMessage.cs
@@ -32,8 +32,8 @@ namespace Org.BouncyCastle.Asn1.Cmp
 
             m_header = PkiHeader.GetInstance(seq[pos++]);
             m_body = PkiBody.GetInstance(seq[pos++]);
-            m_protection = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, DerBitString.GetInstance);
-            m_extraCerts = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Asn1Sequence.GetInstance);
+            m_protection = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, DerBitString.GetTagged);
+            m_extraCerts = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Asn1Sequence.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/cmp/RevRepContent.cs b/crypto/src/asn1/cmp/RevRepContent.cs
index e9b3230c8..6a0910340 100644
--- a/crypto/src/asn1/cmp/RevRepContent.cs
+++ b/crypto/src/asn1/cmp/RevRepContent.cs
@@ -47,8 +47,8 @@ namespace Org.BouncyCastle.Asn1.Cmp
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
             m_status = Asn1Sequence.GetInstance(seq[pos++]);
-			m_revCerts = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1Sequence.GetInstance);
-            m_crls = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Asn1Sequence.GetInstance);
+			m_revCerts = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1Sequence.GetTagged);
+            m_crls = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Asn1Sequence.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/cmp/RootCaKeyUpdateContent.cs b/crypto/src/asn1/cmp/RootCaKeyUpdateContent.cs
index c9782bfd9..6ea159336 100644
--- a/crypto/src/asn1/cmp/RootCaKeyUpdateContent.cs
+++ b/crypto/src/asn1/cmp/RootCaKeyUpdateContent.cs
@@ -52,8 +52,8 @@ namespace Org.BouncyCastle.Asn1.Cmp
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
             m_newWithNew = CmpCertificate.GetInstance(seq[pos++]);
-            m_newWithOld = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, CmpCertificate.GetInstance);
-            m_oldWithNew = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, CmpCertificate.GetInstance);
+            m_newWithOld = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, CmpCertificate.GetTagged);
+            m_oldWithNew = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, CmpCertificate.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/cms/AuthEnvelopedData.cs b/crypto/src/asn1/cms/AuthEnvelopedData.cs
index 62d54b33e..cdc6fd198 100644
--- a/crypto/src/asn1/cms/AuthEnvelopedData.cs
+++ b/crypto/src/asn1/cms/AuthEnvelopedData.cs
@@ -49,12 +49,12 @@ namespace Org.BouncyCastle.Asn1.Cms
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
             m_version = DerInteger.GetInstance(seq[pos++]);
-            m_originatorInfo = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, OriginatorInfo.GetInstance);
+            m_originatorInfo = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, OriginatorInfo.GetTagged);
             m_recipientInfos = Asn1Set.GetInstance(seq[pos++]);
             m_authEncryptedContentInfo = EncryptedContentInfo.GetInstance(seq[pos++]);
-            m_authAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetInstance);
+            m_authAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetTagged);
             m_mac = Asn1OctetString.GetInstance(seq[pos++]);
-            m_unauthAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, false, Asn1Set.GetInstance);
+            m_unauthAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, false, Asn1Set.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/cms/AuthenticatedData.cs b/crypto/src/asn1/cms/AuthenticatedData.cs
index fad7de35f..285a16840 100644
--- a/crypto/src/asn1/cms/AuthenticatedData.cs
+++ b/crypto/src/asn1/cms/AuthenticatedData.cs
@@ -56,14 +56,14 @@ namespace Org.BouncyCastle.Asn1.Cms
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
             m_version = DerInteger.GetInstance(seq[pos++]);
-            m_originatorInfo = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, OriginatorInfo.GetInstance);
+            m_originatorInfo = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, OriginatorInfo.GetTagged);
             m_recipientInfos = Asn1Set.GetInstance(seq[pos++]);
             m_macAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]);
-            m_digestAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, AlgorithmIdentifier.GetInstance);
+            m_digestAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, AlgorithmIdentifier.GetTagged);
             m_encapsulatedContentInfo = ContentInfo.GetInstance(seq[pos++]);
-            m_authAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, false, Asn1Set.GetInstance);
+            m_authAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, false, Asn1Set.GetTagged);
             m_mac = Asn1OctetString.GetInstance(seq[pos++]);
-            m_unauthAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 3, false, Asn1Set.GetInstance);
+            m_unauthAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 3, false, Asn1Set.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/cms/CmsAlgorithmProtection.cs b/crypto/src/asn1/cms/CmsAlgorithmProtection.cs
index 9923b0259..7c538651c 100644
--- a/crypto/src/asn1/cms/CmsAlgorithmProtection.cs
+++ b/crypto/src/asn1/cms/CmsAlgorithmProtection.cs
@@ -76,8 +76,8 @@ namespace Org.BouncyCastle.Asn1.Cms
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
             m_digestAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]);
-            m_signatureAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, AlgorithmIdentifier.GetInstance);
-            m_macAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, false, AlgorithmIdentifier.GetInstance);
+            m_signatureAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, AlgorithmIdentifier.GetTagged);
+            m_macAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, false, AlgorithmIdentifier.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/cms/ContentInfo.cs b/crypto/src/asn1/cms/ContentInfo.cs
index b440b06a9..b9e554984 100644
--- a/crypto/src/asn1/cms/ContentInfo.cs
+++ b/crypto/src/asn1/cms/ContentInfo.cs
@@ -14,10 +14,11 @@ namespace Org.BouncyCastle.Asn1.Cms
             return new ContentInfo(Asn1Sequence.GetInstance(obj));
         }
 
-        public static ContentInfo GetInstance(Asn1TaggedObject obj, bool isExplicit)
-        {
-            return new ContentInfo(Asn1Sequence.GetInstance(obj, isExplicit));
-        }
+        public static ContentInfo GetInstance(Asn1TaggedObject obj, bool isExplicit) =>
+            new ContentInfo(Asn1Sequence.GetInstance(obj, isExplicit));
+
+        public static ContentInfo GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new ContentInfo(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
 
         private readonly DerObjectIdentifier m_contentType;
         private readonly Asn1Encodable m_content;
diff --git a/crypto/src/asn1/cms/EncryptedContentInfo.cs b/crypto/src/asn1/cms/EncryptedContentInfo.cs
index 94a5c00c2..3c9718b80 100644
--- a/crypto/src/asn1/cms/EncryptedContentInfo.cs
+++ b/crypto/src/asn1/cms/EncryptedContentInfo.cs
@@ -46,7 +46,7 @@ namespace Org.BouncyCastle.Asn1.Cms
 
             m_contentType = DerObjectIdentifier.GetInstance(seq[pos++]);
             m_contentEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]);
-            m_encryptedContent = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1OctetString.GetInstance);
+            m_encryptedContent = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1OctetString.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/cms/EncryptedData.cs b/crypto/src/asn1/cms/EncryptedData.cs
index 04ea382c7..03387bcdb 100644
--- a/crypto/src/asn1/cms/EncryptedData.cs
+++ b/crypto/src/asn1/cms/EncryptedData.cs
@@ -43,7 +43,7 @@ namespace Org.BouncyCastle.Asn1.Cms
 
 			m_version = DerInteger.GetInstance(seq[pos++]);
 			m_encryptedContentInfo = EncryptedContentInfo.GetInstance(seq[pos++]);
-			m_unprotectedAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetInstance);
+			m_unprotectedAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/cms/EnvelopedData.cs b/crypto/src/asn1/cms/EnvelopedData.cs
index 846062f1c..4a13b3f3f 100644
--- a/crypto/src/asn1/cms/EnvelopedData.cs
+++ b/crypto/src/asn1/cms/EnvelopedData.cs
@@ -48,10 +48,10 @@ namespace Org.BouncyCastle.Asn1.Cms
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
             m_version = DerInteger.GetInstance(seq[pos++]);
-            m_originatorInfo = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, OriginatorInfo.GetInstance);
+            m_originatorInfo = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, OriginatorInfo.GetTagged);
             m_recipientInfos = Asn1Set.GetInstance(seq[pos++]);
             m_encryptedContentInfo = EncryptedContentInfo.GetInstance(seq[pos++]);
-            m_unprotectedAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetInstance);
+            m_unprotectedAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/cms/Evidence.cs b/crypto/src/asn1/cms/Evidence.cs
index f3687009a..46f55442d 100644
--- a/crypto/src/asn1/cms/Evidence.cs
+++ b/crypto/src/asn1/cms/Evidence.cs
@@ -20,10 +20,11 @@ namespace Org.BouncyCastle.Asn1.Cms
             throw new ArgumentException("Unknown object in GetInstance: " + Platform.GetTypeName(obj), nameof(obj));
         }
 
-        public static Evidence GetInstance(Asn1TaggedObject obj, bool isExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(obj, isExplicit, GetInstance);
-        }
+        public static Evidence GetInstance(Asn1TaggedObject obj, bool isExplicit) =>
+            Asn1Utilities.GetInstanceChoice(obj, isExplicit, GetInstance);
+
+        public static Evidence GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         private readonly TimeStampTokenEvidence m_tstEvidence;
         private readonly EvidenceRecord m_ersEvidence;
diff --git a/crypto/src/asn1/cms/KemRecipientInfo.cs b/crypto/src/asn1/cms/KemRecipientInfo.cs
index ccfae719c..8d650588a 100644
--- a/crypto/src/asn1/cms/KemRecipientInfo.cs
+++ b/crypto/src/asn1/cms/KemRecipientInfo.cs
@@ -72,7 +72,7 @@ namespace Org.BouncyCastle.Asn1.Cms
             m_kemct = Asn1OctetString.GetInstance(seq[pos++]);
             m_kdf = AlgorithmIdentifier.GetInstance(seq[pos++]);
             m_kekLength = DerInteger.GetInstance(seq[pos++]);
-            m_ukm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1OctetString.GetInstance);
+            m_ukm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1OctetString.GetTagged);
             m_wrap = AlgorithmIdentifier.GetInstance(seq[pos++]);
             m_encryptedKey = Asn1OctetString.GetInstance(seq[pos++]);
 
diff --git a/crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs b/crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs
index fb393b9ba..cbbc9d8ba 100644
--- a/crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs
+++ b/crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs
@@ -30,10 +30,11 @@ namespace Org.BouncyCastle.Asn1.Cms
 			throw new ArgumentException("Invalid KeyAgreeRecipientIdentifier: " + Platform.GetTypeName(obj), nameof(obj));
         }
 
-        public static KeyAgreeRecipientIdentifier GetInstance(Asn1TaggedObject obj, bool isExplicit)
-		{
-            return Asn1Utilities.GetInstanceFromChoice(obj, isExplicit, GetInstance);
-		}
+        public static KeyAgreeRecipientIdentifier GetInstance(Asn1TaggedObject obj, bool isExplicit) =>
+            Asn1Utilities.GetInstanceChoice(obj, isExplicit, GetInstance);
+
+        public static KeyAgreeRecipientIdentifier GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
 		private readonly IssuerAndSerialNumber m_issuerSerial;
 		private readonly RecipientKeyIdentifier m_rKeyID;
diff --git a/crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs b/crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs
index c1255adc9..8173005a9 100644
--- a/crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs
+++ b/crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs
@@ -49,8 +49,8 @@ namespace Org.BouncyCastle.Asn1.Cms
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
             m_version = DerInteger.GetInstance(seq[pos++]);
-            m_originator = Asn1Utilities.ReadContextTagged(seq, ref pos, 0, true, OriginatorIdentifierOrKey.GetInstance);
-            m_ukm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Asn1OctetString.GetInstance);
+            m_originator = Asn1Utilities.ReadContextTagged(seq, ref pos, 0, true, OriginatorIdentifierOrKey.GetTagged);
+            m_ukm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Asn1OctetString.GetTagged);
             m_keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]);
             m_recipientEncryptedKeys = Asn1Sequence.GetInstance(seq[pos++]);
 
diff --git a/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs b/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs
index f5cc1f2f7..e4f028ba0 100644
--- a/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs
+++ b/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs
@@ -34,10 +34,11 @@ namespace Org.BouncyCastle.Asn1.Cms
             throw new ArgumentException("Invalid OriginatorIdentifierOrKey: " + Platform.GetTypeName(o), nameof(o));
         }
 
-        public static OriginatorIdentifierOrKey GetInstance(Asn1TaggedObject o, bool explicitly)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(o, explicitly, GetInstance);
-        }
+        public static OriginatorIdentifierOrKey GetInstance(Asn1TaggedObject o, bool explicitly) =>
+            Asn1Utilities.GetInstanceChoice(o, explicitly, GetInstance);
+
+        public static OriginatorIdentifierOrKey GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         private readonly Asn1Encodable m_id;
 
diff --git a/crypto/src/asn1/cms/OriginatorInfo.cs b/crypto/src/asn1/cms/OriginatorInfo.cs
index 74569cbec..6b65dd03f 100644
--- a/crypto/src/asn1/cms/OriginatorInfo.cs
+++ b/crypto/src/asn1/cms/OriginatorInfo.cs
@@ -23,6 +23,13 @@ namespace Org.BouncyCastle.Asn1.Cms
 #pragma warning restore CS0618 // Type or member is obsolete
         }
 
+        public static OriginatorInfo GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+#pragma warning disable CS0618 // Type or member is obsolete
+            return new OriginatorInfo(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
+#pragma warning restore CS0618 // Type or member is obsolete
+        }
+
         private readonly Asn1Set m_certs;
         private readonly Asn1Set m_crls;
 
@@ -39,8 +46,8 @@ namespace Org.BouncyCastle.Asn1.Cms
             if (count < 0 || count > 2)
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-            m_certs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetInstance);
-            m_crls = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetInstance);
+            m_certs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetTagged);
+            m_crls = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/cms/PasswordRecipientInfo.cs b/crypto/src/asn1/cms/PasswordRecipientInfo.cs
index 41ab686ef..a359cd12a 100644
--- a/crypto/src/asn1/cms/PasswordRecipientInfo.cs
+++ b/crypto/src/asn1/cms/PasswordRecipientInfo.cs
@@ -53,7 +53,7 @@ namespace Org.BouncyCastle.Asn1.Cms
 
             m_version = DerInteger.GetInstance(seq[pos++]);
             m_keyDerivationAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false,
-                AlgorithmIdentifier.GetInstance);
+                AlgorithmIdentifier.GetTagged);
             m_keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]);
             m_encryptedKey = Asn1OctetString.GetInstance(seq[pos++]);
         }
diff --git a/crypto/src/asn1/cms/RecipientIdentifier.cs b/crypto/src/asn1/cms/RecipientIdentifier.cs
index 4fe181dff..24469b305 100644
--- a/crypto/src/asn1/cms/RecipientIdentifier.cs
+++ b/crypto/src/asn1/cms/RecipientIdentifier.cs
@@ -23,10 +23,11 @@ namespace Org.BouncyCastle.Asn1.Cms
             throw new ArgumentException("Illegal object in RecipientIdentifier: " + Platform.GetTypeName(o), nameof(o));
         }
 
-        public static RecipientIdentifier GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static RecipientIdentifier GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public static RecipientIdentifier GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         private readonly Asn1Encodable m_id;
 
diff --git a/crypto/src/asn1/cms/RecipientInfo.cs b/crypto/src/asn1/cms/RecipientInfo.cs
index 424ea4d10..cb98e4784 100644
--- a/crypto/src/asn1/cms/RecipientInfo.cs
+++ b/crypto/src/asn1/cms/RecipientInfo.cs
@@ -24,10 +24,11 @@ namespace Org.BouncyCastle.Asn1.Cms
             throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(o), nameof(o));
         }
 
-        public static RecipientInfo GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static RecipientInfo GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public static RecipientInfo GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         private readonly Asn1Encodable m_info;
 
diff --git a/crypto/src/asn1/cms/SCVPReqRes.cs b/crypto/src/asn1/cms/SCVPReqRes.cs
index 11df63ea9..77c82d9a9 100644
--- a/crypto/src/asn1/cms/SCVPReqRes.cs
+++ b/crypto/src/asn1/cms/SCVPReqRes.cs
@@ -28,7 +28,7 @@ namespace Org.BouncyCastle.Asn1.Cms
             if (count < 1 || count > 2)
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-            m_request = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, ContentInfo.GetInstance);
+            m_request = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, ContentInfo.GetTagged);
             m_response = ContentInfo.GetInstance(seq[pos++]);
 
             if (pos != count)
diff --git a/crypto/src/asn1/cms/SignerIdentifier.cs b/crypto/src/asn1/cms/SignerIdentifier.cs
index 055a393df..8899d94e9 100644
--- a/crypto/src/asn1/cms/SignerIdentifier.cs
+++ b/crypto/src/asn1/cms/SignerIdentifier.cs
@@ -27,10 +27,11 @@ namespace Org.BouncyCastle.Asn1.Cms
             throw new ArgumentException("Illegal object in SignerIdentifier: " + Platform.GetTypeName(o), nameof(o));
         }
 
-        public static SignerIdentifier GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static SignerIdentifier GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public static SignerIdentifier GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         private readonly Asn1Encodable m_id;
 
diff --git a/crypto/src/asn1/cms/SignerInfo.cs b/crypto/src/asn1/cms/SignerInfo.cs
index fbd4bcca7..5866f98da 100644
--- a/crypto/src/asn1/cms/SignerInfo.cs
+++ b/crypto/src/asn1/cms/SignerInfo.cs
@@ -59,10 +59,10 @@ namespace Org.BouncyCastle.Asn1.Cms
             m_version = DerInteger.GetInstance(seq[pos++]);
             m_sid = SignerIdentifier.GetInstance(seq[pos++]);
             m_digAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]);
-            m_authenticatedAttributes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetInstance);
+            m_authenticatedAttributes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetTagged);
             m_digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]);
             m_encryptedDigest = Asn1OctetString.GetInstance(seq[pos++]);
-            m_unauthenticatedAttributes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetInstance);
+            m_unauthenticatedAttributes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/cms/Time.cs b/crypto/src/asn1/cms/Time.cs
index 8dbca7a27..f59d9f63c 100644
--- a/crypto/src/asn1/cms/Time.cs
+++ b/crypto/src/asn1/cms/Time.cs
@@ -23,10 +23,11 @@ namespace Org.BouncyCastle.Asn1.Cms
             throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), nameof(obj));
         }
 
-        public static Time GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static Time GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public static Time GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         public static Time GetOptional(Asn1Encodable element)
         {
diff --git a/crypto/src/asn1/cms/ecc/MQVuserKeyingMaterial.cs b/crypto/src/asn1/cms/ecc/MQVuserKeyingMaterial.cs
index 68a6367e5..1cb4f4ff5 100644
--- a/crypto/src/asn1/cms/ecc/MQVuserKeyingMaterial.cs
+++ b/crypto/src/asn1/cms/ecc/MQVuserKeyingMaterial.cs
@@ -36,7 +36,7 @@ namespace Org.BouncyCastle.Asn1.Cms.Ecc
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
             m_ephemeralPublicKey = OriginatorPublicKey.GetInstance(seq[pos++]);
-			m_addedukm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1OctetString.GetInstance);
+			m_addedukm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1OctetString.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/crmf/CertId.cs b/crypto/src/asn1/crmf/CertId.cs
index c9f66b065..a1eabea11 100644
--- a/crypto/src/asn1/crmf/CertId.cs
+++ b/crypto/src/asn1/crmf/CertId.cs
@@ -16,10 +16,11 @@ namespace Org.BouncyCastle.Asn1.Crmf
             return new CertId(Asn1Sequence.GetInstance(obj));
         }
 
-        public static CertId GetInstance(Asn1TaggedObject obj, bool isExplicit)
-        {
-            return new CertId(Asn1Sequence.GetInstance(obj, isExplicit));
-        }
+        public static CertId GetInstance(Asn1TaggedObject obj, bool isExplicit) =>
+            new CertId(Asn1Sequence.GetInstance(obj, isExplicit));
+
+        public static CertId GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new CertId(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
 
         private readonly GeneralName m_issuer;
         private readonly DerInteger m_serialNumber;
diff --git a/crypto/src/asn1/crmf/CertTemplate.cs b/crypto/src/asn1/crmf/CertTemplate.cs
index 62227808c..6ae529e9b 100644
--- a/crypto/src/asn1/crmf/CertTemplate.cs
+++ b/crypto/src/asn1/crmf/CertTemplate.cs
@@ -42,16 +42,16 @@ namespace Org.BouncyCastle.Asn1.Crmf
 
             int pos = 0;
 
-            m_version = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, DerInteger.GetInstance);
-            m_serialNumber = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, DerInteger.GetInstance);
-            m_signingAlg = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, false, AlgorithmIdentifier.GetInstance);
-            m_issuer = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 3, true, X509Name.GetInstance); // CHOICE Name
-            m_validity = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 4, false, OptionalValidity.GetInstance);
-            m_subject = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 5, true, X509Name.GetInstance); // CHOICE Name
-            m_publicKey = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 6, false, SubjectPublicKeyInfo.GetInstance);
-            m_issuerUID = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 7, false, DerBitString.GetInstance);
-            m_subjectUID = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 8, false, DerBitString.GetInstance);
-            m_extensions = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 9, false, X509Extensions.GetInstance);
+            m_version = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, DerInteger.GetTagged);
+            m_serialNumber = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, DerInteger.GetTagged);
+            m_signingAlg = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, false, AlgorithmIdentifier.GetTagged);
+            m_issuer = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 3, true, X509Name.GetTagged); // CHOICE Name
+            m_validity = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 4, false, OptionalValidity.GetTagged);
+            m_subject = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 5, true, X509Name.GetTagged); // CHOICE Name
+            m_publicKey = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 6, false, SubjectPublicKeyInfo.GetTagged);
+            m_issuerUID = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 7, false, DerBitString.GetTagged);
+            m_subjectUID = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 8, false, DerBitString.GetTagged);
+            m_extensions = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 9, false, X509Extensions.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/crmf/EncryptedKey.cs b/crypto/src/asn1/crmf/EncryptedKey.cs
index 62c475f5d..6eae55da4 100644
--- a/crypto/src/asn1/crmf/EncryptedKey.cs
+++ b/crypto/src/asn1/crmf/EncryptedKey.cs
@@ -16,10 +16,11 @@ namespace Org.BouncyCastle.Asn1.Crmf
             return new EncryptedKey(EncryptedValue.GetInstance(obj));
         }
 
-        public static EncryptedKey GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static EncryptedKey GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public static EncryptedKey GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         private readonly EnvelopedData m_envelopedData;
         private readonly EncryptedValue m_encryptedValue;
diff --git a/crypto/src/asn1/crmf/OptionalValidity.cs b/crypto/src/asn1/crmf/OptionalValidity.cs
index 290d1905e..9abeaca87 100644
--- a/crypto/src/asn1/crmf/OptionalValidity.cs
+++ b/crypto/src/asn1/crmf/OptionalValidity.cs
@@ -16,10 +16,11 @@ namespace Org.BouncyCastle.Asn1.Crmf
             return new OptionalValidity(Asn1Sequence.GetInstance(obj));
         }
 
-        public static OptionalValidity GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return new OptionalValidity(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
-        }
+        public static OptionalValidity GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new OptionalValidity(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+
+        public static OptionalValidity GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new OptionalValidity(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
 
         private readonly Time m_notBefore;
         private readonly Time m_notAfter;
@@ -34,8 +35,8 @@ namespace Org.BouncyCastle.Asn1.Crmf
 
             int pos = 0;
 
-            m_notBefore = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Time.GetInstance);
-            m_notAfter = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Time.GetInstance);
+            m_notBefore = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Time.GetTagged);
+            m_notAfter = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Time.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/crmf/PKIArchiveOptions.cs b/crypto/src/asn1/crmf/PKIArchiveOptions.cs
index a702d6dc2..37e9af83e 100644
--- a/crypto/src/asn1/crmf/PKIArchiveOptions.cs
+++ b/crypto/src/asn1/crmf/PKIArchiveOptions.cs
@@ -26,10 +26,8 @@ namespace Org.BouncyCastle.Asn1.Crmf
             throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), nameof(obj));
         }
 
-        public static PkiArchiveOptions GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static PkiArchiveOptions GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
 
         public static PkiArchiveOptions GetOptional(Asn1Encodable element)
         {
@@ -49,6 +47,9 @@ namespace Org.BouncyCastle.Asn1.Crmf
             return null;
         }
 
+        public static PkiArchiveOptions GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
+
         private static Asn1Encodable GetOptionalBaseObject(Asn1TaggedObject taggedObject)
         {
             if (taggedObject.HasContextTag())
diff --git a/crypto/src/asn1/crmf/PKIPublicationInfo.cs b/crypto/src/asn1/crmf/PKIPublicationInfo.cs
index 3c12dffa5..01a258b98 100644
--- a/crypto/src/asn1/crmf/PKIPublicationInfo.cs
+++ b/crypto/src/asn1/crmf/PKIPublicationInfo.cs
@@ -31,10 +31,11 @@ namespace Org.BouncyCastle.Asn1.Crmf
             return new PkiPublicationInfo(Asn1Sequence.GetInstance(obj));
         }
 
-        public static PkiPublicationInfo GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return new PkiPublicationInfo(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
-        }
+        public static PkiPublicationInfo GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new PkiPublicationInfo(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+
+        public static PkiPublicationInfo GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new PkiPublicationInfo(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
 
         private readonly DerInteger m_action;
         private readonly Asn1Sequence m_pubInfos;
diff --git a/crypto/src/asn1/crmf/PopoPrivKey.cs b/crypto/src/asn1/crmf/PopoPrivKey.cs
index 91b1ddba4..33ee8744f 100644
--- a/crypto/src/asn1/crmf/PopoPrivKey.cs
+++ b/crypto/src/asn1/crmf/PopoPrivKey.cs
@@ -29,10 +29,8 @@ namespace Org.BouncyCastle.Asn1.Crmf
             throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), nameof(obj));
         }
 
-        public static PopoPrivKey GetInstance(Asn1TaggedObject tagged, bool isExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(tagged, isExplicit, GetInstance);
-        }
+        public static PopoPrivKey GetInstance(Asn1TaggedObject tagged, bool isExplicit) =>
+            Asn1Utilities.GetInstanceChoice(tagged, isExplicit, GetInstance);
 
         public static PopoPrivKey GetOptional(Asn1Encodable element)
         {
@@ -52,6 +50,9 @@ namespace Org.BouncyCastle.Asn1.Crmf
             return null;
         }
 
+        public static PopoPrivKey GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
+
         private static Asn1Encodable GetOptionalBaseObject(Asn1TaggedObject taggedObject)
         {
             if (taggedObject.HasContextTag())
diff --git a/crypto/src/asn1/crmf/PopoSigningKey.cs b/crypto/src/asn1/crmf/PopoSigningKey.cs
index 00138ddb3..a0b6cad35 100644
--- a/crypto/src/asn1/crmf/PopoSigningKey.cs
+++ b/crypto/src/asn1/crmf/PopoSigningKey.cs
@@ -33,7 +33,7 @@ namespace Org.BouncyCastle.Asn1.Crmf
 
             int pos = 0;
 
-            m_poposkInput = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, PopoSigningKeyInput.GetInstance);
+            m_poposkInput = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, PopoSigningKeyInput.GetTagged);
             m_algorithmIdentifier = AlgorithmIdentifier.GetInstance(seq[pos++]);
             m_signature = DerBitString.GetInstance(seq[pos++]);
 
diff --git a/crypto/src/asn1/crmf/PopoSigningKeyInput.cs b/crypto/src/asn1/crmf/PopoSigningKeyInput.cs
index c62159051..189cb9681 100644
--- a/crypto/src/asn1/crmf/PopoSigningKeyInput.cs
+++ b/crypto/src/asn1/crmf/PopoSigningKeyInput.cs
@@ -16,10 +16,11 @@ namespace Org.BouncyCastle.Asn1.Crmf
             return new PopoSigningKeyInput(Asn1Sequence.GetInstance(obj));
         }
 
-        public static PopoSigningKeyInput GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return new PopoSigningKeyInput(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
-        }
+        public static PopoSigningKeyInput GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new PopoSigningKeyInput(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+
+        public static PopoSigningKeyInput GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new PopoSigningKeyInput(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
 
         private readonly GeneralName m_sender;
         private readonly PKMacValue m_publicKeyMac;
diff --git a/crypto/src/asn1/crmf/ProofOfPossession.cs b/crypto/src/asn1/crmf/ProofOfPossession.cs
index d7d9fe7b1..0b0ce1c3a 100644
--- a/crypto/src/asn1/crmf/ProofOfPossession.cs
+++ b/crypto/src/asn1/crmf/ProofOfPossession.cs
@@ -28,10 +28,8 @@ namespace Org.BouncyCastle.Asn1.Crmf
             throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), nameof(obj));
         }
 
-        public static ProofOfPossession GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static ProofOfPossession GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
 
         public static ProofOfPossession GetOptional(Asn1Encodable element)
         {
@@ -51,6 +49,9 @@ namespace Org.BouncyCastle.Asn1.Crmf
             return null;
         }
 
+        public static ProofOfPossession GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
+
         private static Asn1Encodable GetOptionalBaseObject(Asn1TaggedObject taggedObject)
         {
             if (taggedObject.HasContextTag())
diff --git a/crypto/src/asn1/esf/CrlListID.cs b/crypto/src/asn1/esf/CrlListID.cs
index ef49f9f4f..f9ca95e24 100644
--- a/crypto/src/asn1/esf/CrlListID.cs
+++ b/crypto/src/asn1/esf/CrlListID.cs
@@ -24,10 +24,11 @@ namespace Org.BouncyCastle.Asn1.Esf
             return new CrlListID(Asn1Sequence.GetInstance(obj));
         }
 
-        public static CrlListID GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return new CrlListID(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
-        }
+        public static CrlListID GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new CrlListID(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+
+        public static CrlListID GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new CrlListID(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
 
         private readonly Asn1Sequence m_crls;
 
diff --git a/crypto/src/asn1/esf/CrlOcspRef.cs b/crypto/src/asn1/esf/CrlOcspRef.cs
index 2d8dc1bc3..2f14dc4b1 100644
--- a/crypto/src/asn1/esf/CrlOcspRef.cs
+++ b/crypto/src/asn1/esf/CrlOcspRef.cs
@@ -41,9 +41,9 @@ namespace Org.BouncyCastle.Asn1.Esf
 
             int pos = 0;
 
-			m_crlids = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, CrlListID.GetInstance);
-            m_ocspids = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, OcspListID.GetInstance);
-            m_otherRev = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, OtherRevRefs.GetInstance);
+			m_crlids = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, CrlListID.GetTagged);
+            m_ocspids = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, OcspListID.GetTagged);
+            m_otherRev = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, OtherRevRefs.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/esf/OcspListID.cs b/crypto/src/asn1/esf/OcspListID.cs
index 06eb99fc4..a821e6b17 100644
--- a/crypto/src/asn1/esf/OcspListID.cs
+++ b/crypto/src/asn1/esf/OcspListID.cs
@@ -23,10 +23,11 @@ namespace Org.BouncyCastle.Asn1.Esf
             return new OcspListID(Asn1Sequence.GetInstance(obj));
         }
 
-        public static OcspListID GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return new OcspListID(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
-        }
+        public static OcspListID GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new OcspListID(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+
+        public static OcspListID GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new OcspListID(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
 
         private readonly Asn1Sequence m_ocspResponses;
 
diff --git a/crypto/src/asn1/esf/OtherHash.cs b/crypto/src/asn1/esf/OtherHash.cs
index 0d8888234..58ef2ee9a 100644
--- a/crypto/src/asn1/esf/OtherHash.cs
+++ b/crypto/src/asn1/esf/OtherHash.cs
@@ -29,10 +29,11 @@ namespace Org.BouncyCastle.Asn1.Esf
             return new OtherHash(OtherHashAlgAndValue.GetInstance(obj));
         }
 
-        public static OtherHash GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static OtherHash GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public static OtherHash GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         private readonly Asn1OctetString m_sha1Hash;
         private readonly OtherHashAlgAndValue m_otherHash;
diff --git a/crypto/src/asn1/esf/OtherRevRefs.cs b/crypto/src/asn1/esf/OtherRevRefs.cs
index 3aeade98c..d866fef5d 100644
--- a/crypto/src/asn1/esf/OtherRevRefs.cs
+++ b/crypto/src/asn1/esf/OtherRevRefs.cs
@@ -26,10 +26,11 @@ namespace Org.BouncyCastle.Asn1.Esf
 			return new OtherRevRefs(Asn1Sequence.GetInstance(obj));
 		}
 
-        public static OtherRevRefs GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return new OtherRevRefs(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
-        }
+        public static OtherRevRefs GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new OtherRevRefs(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+
+        public static OtherRevRefs GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new OtherRevRefs(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
 
         private readonly DerObjectIdentifier m_otherRevRefType;
         private readonly Asn1Encodable m_otherRevRefs;
diff --git a/crypto/src/asn1/esf/OtherRevVals.cs b/crypto/src/asn1/esf/OtherRevVals.cs
index 6459f0657..84a12e820 100644
--- a/crypto/src/asn1/esf/OtherRevVals.cs
+++ b/crypto/src/asn1/esf/OtherRevVals.cs
@@ -26,10 +26,11 @@ namespace Org.BouncyCastle.Asn1.Esf
             return new OtherRevVals(Asn1Sequence.GetInstance(obj));
         }
 
-        public static OtherRevVals GetInstance(Asn1TaggedObject obj, bool explicitly)
-        {
-            return new OtherRevVals(Asn1Sequence.GetInstance(obj, explicitly));
-        }
+        public static OtherRevVals GetInstance(Asn1TaggedObject obj, bool explicitly) =>
+            new OtherRevVals(Asn1Sequence.GetInstance(obj, explicitly));
+
+        public static OtherRevVals GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new OtherRevVals(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
 
         private readonly DerObjectIdentifier m_otherRevValType;
         private readonly Asn1Encodable m_otherRevVals;
diff --git a/crypto/src/asn1/esf/RevocationValues.cs b/crypto/src/asn1/esf/RevocationValues.cs
index eef246ee8..2d9175275 100644
--- a/crypto/src/asn1/esf/RevocationValues.cs
+++ b/crypto/src/asn1/esf/RevocationValues.cs
@@ -45,13 +45,13 @@ namespace Org.BouncyCastle.Asn1.Esf
 
 			int pos = 0;
 
-			m_crlVals = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1Sequence.GetInstance);
+			m_crlVals = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1Sequence.GetTagged);
             m_crlVals?.MapElements(CertificateList.GetInstance); // Validate
 
-            m_ocspVals = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Asn1Sequence.GetInstance);
+            m_ocspVals = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Asn1Sequence.GetTagged);
             m_ocspVals?.MapElements(BasicOcspResponse.GetInstance); // Validate
 
-            m_otherRevVals = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, OtherRevVals.GetInstance);
+            m_otherRevVals = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, OtherRevVals.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/esf/SignaturePolicyIdentifier.cs b/crypto/src/asn1/esf/SignaturePolicyIdentifier.cs
index eb6c0654c..809a757ac 100644
--- a/crypto/src/asn1/esf/SignaturePolicyIdentifier.cs
+++ b/crypto/src/asn1/esf/SignaturePolicyIdentifier.cs
@@ -31,10 +31,11 @@ namespace Org.BouncyCastle.Asn1.Esf
 			return new SignaturePolicyIdentifier(SignaturePolicyId.GetInstance(obj));
 		}
 
-        public static SignaturePolicyIdentifier GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static SignaturePolicyIdentifier GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public static SignaturePolicyIdentifier GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         private readonly SignaturePolicyId m_sigPolicy;
 
diff --git a/crypto/src/asn1/esf/SignerLocation.cs b/crypto/src/asn1/esf/SignerLocation.cs
index c4f5e6521..22bbfecac 100644
--- a/crypto/src/asn1/esf/SignerLocation.cs
+++ b/crypto/src/asn1/esf/SignerLocation.cs
@@ -45,10 +45,10 @@ namespace Org.BouncyCastle.Asn1.Esf
 
             int pos = 0;
 
-            m_countryName = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, DirectoryString.GetInstance);
-            m_localityName = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, DirectoryString.GetInstance);
+            m_countryName = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, DirectoryString.GetTagged);
+            m_localityName = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, DirectoryString.GetTagged);
 
-            m_postalAddress = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, Asn1Sequence.GetInstance);
+            m_postalAddress = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, Asn1Sequence.GetTagged);
             if (m_postalAddress != null)
             {
                 if (m_postalAddress.Count > 6)
diff --git a/crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs b/crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs
index e2de8882d..7aaa9601c 100644
--- a/crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs
+++ b/crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs
@@ -70,10 +70,11 @@ namespace Org.BouncyCastle.Asn1.IsisMtt.Ocsp
             throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj");
 		}
 
-		public static RequestedCertificate GetInstance(Asn1TaggedObject obj, bool isExplicit)
-		{
-			return Asn1Utilities.GetInstanceFromChoice(obj, isExplicit, GetInstance);
-		}
+		public static RequestedCertificate GetInstance(Asn1TaggedObject obj, bool isExplicit) =>
+			Asn1Utilities.GetInstanceChoice(obj, isExplicit, GetInstance);
+
+        public static RequestedCertificate GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
 		private RequestedCertificate(
 			Asn1TaggedObject tagged)
diff --git a/crypto/src/asn1/ocsp/BasicOCSPResponse.cs b/crypto/src/asn1/ocsp/BasicOCSPResponse.cs
index fc491f78e..0b8b48e43 100644
--- a/crypto/src/asn1/ocsp/BasicOCSPResponse.cs
+++ b/crypto/src/asn1/ocsp/BasicOCSPResponse.cs
@@ -46,7 +46,7 @@ namespace Org.BouncyCastle.Asn1.Ocsp
             m_tbsResponseData = ResponseData.GetInstance(seq[pos++]);
             m_signatureAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]);
             m_signature = DerBitString.GetInstance(seq[pos++]);
-            m_certs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1Sequence.GetInstance);
+            m_certs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1Sequence.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/ocsp/CertStatus.cs b/crypto/src/asn1/ocsp/CertStatus.cs
index 7ce44ea3f..c67fdb5f6 100644
--- a/crypto/src/asn1/ocsp/CertStatus.cs
+++ b/crypto/src/asn1/ocsp/CertStatus.cs
@@ -14,10 +14,11 @@ namespace Org.BouncyCastle.Asn1.Ocsp
             return new CertStatus(Asn1TaggedObject.GetInstance(obj));
         }
 
-        public static CertStatus GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static CertStatus GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public static CertStatus GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         private static Asn1Encodable GetValue(Asn1TaggedObject choice)
         {
diff --git a/crypto/src/asn1/ocsp/CrlID.cs b/crypto/src/asn1/ocsp/CrlID.cs
index c85b38ae8..4ff1a9cab 100644
--- a/crypto/src/asn1/ocsp/CrlID.cs
+++ b/crypto/src/asn1/ocsp/CrlID.cs
@@ -36,9 +36,9 @@ namespace Org.BouncyCastle.Asn1.Ocsp
 
             int pos = 0;
 
-            m_crlUrl = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, DerIA5String.GetInstance);
-            m_crlNum = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, DerInteger.GetInstance);
-            m_crlTime = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, Asn1GeneralizedTime.GetInstance);
+            m_crlUrl = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, DerIA5String.GetTagged);
+            m_crlNum = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, DerInteger.GetTagged);
+            m_crlTime = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, Asn1GeneralizedTime.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/ocsp/OCSPRequest.cs b/crypto/src/asn1/ocsp/OCSPRequest.cs
index da5e1e5db..02a1285ca 100644
--- a/crypto/src/asn1/ocsp/OCSPRequest.cs
+++ b/crypto/src/asn1/ocsp/OCSPRequest.cs
@@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Asn1.Ocsp
             int pos = 0;
 
             m_tbsRequest = TbsRequest.GetInstance(seq[pos++]);
-            m_optionalSignature = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Signature.GetInstance);
+            m_optionalSignature = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Signature.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/ocsp/OCSPResponse.cs b/crypto/src/asn1/ocsp/OCSPResponse.cs
index c93a88f4f..ff2a0ea6d 100644
--- a/crypto/src/asn1/ocsp/OCSPResponse.cs
+++ b/crypto/src/asn1/ocsp/OCSPResponse.cs
@@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Asn1.Ocsp
             int pos = 0;
 
             m_responseStatus = new OcspResponseStatus(DerEnumerated.GetInstance(seq[pos++]));
-            m_responseBytes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, ResponseBytes.GetInstance);
+            m_responseBytes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, ResponseBytes.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/ocsp/Request.cs b/crypto/src/asn1/ocsp/Request.cs
index c6fb6ae47..9439e382a 100644
--- a/crypto/src/asn1/ocsp/Request.cs
+++ b/crypto/src/asn1/ocsp/Request.cs
@@ -39,7 +39,7 @@ namespace Org.BouncyCastle.Asn1.Ocsp
             int pos = 0;
 
             m_reqCert = CertID.GetInstance(seq[pos++]);
-            m_singleRequestExtensions = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, X509Extensions.GetInstance);
+            m_singleRequestExtensions = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, X509Extensions.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/ocsp/ResponderID.cs b/crypto/src/asn1/ocsp/ResponderID.cs
index aea935e06..3cab8c260 100644
--- a/crypto/src/asn1/ocsp/ResponderID.cs
+++ b/crypto/src/asn1/ocsp/ResponderID.cs
@@ -29,10 +29,11 @@ namespace Org.BouncyCastle.Asn1.Ocsp
 			return new ResponderID(X509Name.GetInstance(obj));
 		}
 
-        public static ResponderID GetInstance(Asn1TaggedObject obj, bool isExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(obj, isExplicit, GetInstance);
-        }
+        public static ResponderID GetInstance(Asn1TaggedObject obj, bool isExplicit) =>
+            Asn1Utilities.GetInstanceChoice(obj, isExplicit, GetInstance);
+
+        public static ResponderID GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         private readonly Asn1Encodable m_id;
 
diff --git a/crypto/src/asn1/ocsp/ResponseBytes.cs b/crypto/src/asn1/ocsp/ResponseBytes.cs
index c5cbc3d3f..9b8d80132 100644
--- a/crypto/src/asn1/ocsp/ResponseBytes.cs
+++ b/crypto/src/asn1/ocsp/ResponseBytes.cs
@@ -14,10 +14,11 @@ namespace Org.BouncyCastle.Asn1.Ocsp
             return new ResponseBytes(Asn1Sequence.GetInstance(obj));
         }
 
-        public static ResponseBytes GetInstance(Asn1TaggedObject obj, bool explicitly)
-        {
-            return new ResponseBytes(Asn1Sequence.GetInstance(obj, explicitly));
-        }
+        public static ResponseBytes GetInstance(Asn1TaggedObject obj, bool explicitly) =>
+            new ResponseBytes(Asn1Sequence.GetInstance(obj, explicitly));
+
+        public static ResponseBytes GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new ResponseBytes(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
 
         private readonly DerObjectIdentifier m_responseType;
         private readonly Asn1OctetString m_response;
diff --git a/crypto/src/asn1/ocsp/ResponseData.cs b/crypto/src/asn1/ocsp/ResponseData.cs
index 81ea2d0d3..300501b5c 100644
--- a/crypto/src/asn1/ocsp/ResponseData.cs
+++ b/crypto/src/asn1/ocsp/ResponseData.cs
@@ -56,7 +56,7 @@ namespace Org.BouncyCastle.Asn1.Ocsp
             int pos = 0;
 
             {
-                DerInteger version = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, DerInteger.GetInstance);
+                DerInteger version = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, DerInteger.GetTagged);
 
                 m_version = version ?? V1;
                 m_versionPresent = version != null;
@@ -65,7 +65,7 @@ namespace Org.BouncyCastle.Asn1.Ocsp
             m_responderID = ResponderID.GetInstance(seq[pos++]);
             m_producedAt = Asn1GeneralizedTime.GetInstance(seq[pos++]);
             m_responses = Asn1Sequence.GetInstance(seq[pos++]);
-            m_responseExtensions = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, X509Extensions.GetInstance);
+            m_responseExtensions = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, X509Extensions.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/ocsp/RevokedInfo.cs b/crypto/src/asn1/ocsp/RevokedInfo.cs
index d2395e186..83b03b0eb 100644
--- a/crypto/src/asn1/ocsp/RevokedInfo.cs
+++ b/crypto/src/asn1/ocsp/RevokedInfo.cs
@@ -46,7 +46,7 @@ namespace Org.BouncyCastle.Asn1.Ocsp
             m_revocationTime = Asn1GeneralizedTime.GetInstance(seq[pos++]);
 
             m_revocationReason = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true,
-                (t, e) => new CrlReason(DerEnumerated.GetInstance(t, e)));
+                (t, e) => new CrlReason(DerEnumerated.GetTagged(t, e)));
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/ocsp/Signature.cs b/crypto/src/asn1/ocsp/Signature.cs
index fd77b87b1..720f9f634 100644
--- a/crypto/src/asn1/ocsp/Signature.cs
+++ b/crypto/src/asn1/ocsp/Signature.cs
@@ -16,10 +16,11 @@ namespace Org.BouncyCastle.Asn1.Ocsp
             return new Signature(Asn1Sequence.GetInstance(obj));
 		}
 
-        public static Signature GetInstance(Asn1TaggedObject obj, bool explicitly)
-        {
-            return new Signature(Asn1Sequence.GetInstance(obj, explicitly));
-        }
+        public static Signature GetInstance(Asn1TaggedObject obj, bool explicitly) =>
+            new Signature(Asn1Sequence.GetInstance(obj, explicitly));
+
+        public static Signature GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new Signature(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
 
         private readonly AlgorithmIdentifier m_signatureAlgorithm;
         private readonly DerBitString m_signatureValue;
@@ -47,7 +48,7 @@ namespace Org.BouncyCastle.Asn1.Ocsp
 
             m_signatureAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]);
             m_signatureValue = DerBitString.GetInstance(seq[pos++]);
-            m_certs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1Sequence.GetInstance);
+            m_certs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1Sequence.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/ocsp/SingleResponse.cs b/crypto/src/asn1/ocsp/SingleResponse.cs
index c2188562b..60266579d 100644
--- a/crypto/src/asn1/ocsp/SingleResponse.cs
+++ b/crypto/src/asn1/ocsp/SingleResponse.cs
@@ -53,8 +53,8 @@ namespace Org.BouncyCastle.Asn1.Ocsp
             m_certID = CertID.GetInstance(seq[pos++]);
             m_certStatus = CertStatus.GetInstance(seq[pos++]);
             m_thisUpdate = Asn1GeneralizedTime.GetInstance(seq[pos++]);
-            m_nextUpdate = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1GeneralizedTime.GetInstance);
-            m_singleExtensions = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, X509Extensions.GetInstance);
+            m_nextUpdate = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1GeneralizedTime.GetTagged);
+            m_singleExtensions = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, X509Extensions.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/ocsp/TBSRequest.cs b/crypto/src/asn1/ocsp/TBSRequest.cs
index 8f44464d1..3501b0c35 100644
--- a/crypto/src/asn1/ocsp/TBSRequest.cs
+++ b/crypto/src/asn1/ocsp/TBSRequest.cs
@@ -47,15 +47,15 @@ namespace Org.BouncyCastle.Asn1.Ocsp
             int pos = 0;
 
             {
-                DerInteger version = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, DerInteger.GetInstance);
+                DerInteger version = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, DerInteger.GetTagged);
 
                 m_version = version ?? V1;
                 m_versionPresent = version != null;
             }
 
-            m_requestorName = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, GeneralName.GetInstance);
+            m_requestorName = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, GeneralName.GetTagged);
 			m_requestList = Asn1Sequence.GetInstance(seq[pos++]);
-            m_requestExtensions = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, X509Extensions.GetInstance);
+            m_requestExtensions = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, X509Extensions.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/pkcs/CertificationRequestInfo.cs b/crypto/src/asn1/pkcs/CertificationRequestInfo.cs
index 53bdffdaa..38d2d39dd 100644
--- a/crypto/src/asn1/pkcs/CertificationRequestInfo.cs
+++ b/crypto/src/asn1/pkcs/CertificationRequestInfo.cs
@@ -63,7 +63,7 @@ namespace Org.BouncyCastle.Asn1.Pkcs
             m_subjectPKInfo = SubjectPublicKeyInfo.GetInstance(seq[pos++]);
 
             // NOTE: some CertificationRequestInfo objects seem to treat this field as optional.
-            m_attributes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetInstance);
+            m_attributes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/pkcs/PrivateKeyInfo.cs b/crypto/src/asn1/pkcs/PrivateKeyInfo.cs
index 7397b7061..1185cf2f8 100644
--- a/crypto/src/asn1/pkcs/PrivateKeyInfo.cs
+++ b/crypto/src/asn1/pkcs/PrivateKeyInfo.cs
@@ -53,11 +53,27 @@ namespace Org.BouncyCastle.Asn1.Pkcs
             return new PrivateKeyInfo(Asn1Sequence.GetInstance(obj));
         }
 
-        public static PrivateKeyInfo GetInstance(Asn1TaggedObject obj, bool explicitly)
+        public static PrivateKeyInfo GetInstance(Asn1TaggedObject obj, bool explicitly) =>
+            new PrivateKeyInfo(Asn1Sequence.GetInstance(obj, explicitly));
+
+        public static PrivateKeyInfo GetOptional(Asn1Encodable element)
         {
-            return new PrivateKeyInfo(Asn1Sequence.GetInstance(obj, explicitly));
+            if (element == null)
+                throw new ArgumentNullException(nameof(element));
+
+            if (element is PrivateKeyInfo privateKeyInfo)
+                return privateKeyInfo;
+
+            Asn1Sequence asn1Sequence = Asn1Sequence.GetOptional(element);
+            if (asn1Sequence != null)
+                return new PrivateKeyInfo(asn1Sequence);
+
+            return null;
         }
 
+        public static PrivateKeyInfo GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new PrivateKeyInfo(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
+
         private readonly DerInteger m_version;
         private readonly AlgorithmIdentifier m_privateKeyAlgorithm;
         private readonly Asn1OctetString m_privateKey;
@@ -73,8 +89,8 @@ namespace Org.BouncyCastle.Asn1.Pkcs
             m_version = DerInteger.GetInstance(seq[pos++]);
             m_privateKeyAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]);
             m_privateKey = Asn1OctetString.GetInstance(seq[pos++]);
-            m_attributes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetInstance);
-            m_publicKey = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, DerBitString.GetInstance);
+            m_attributes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetTagged);
+            m_publicKey = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, DerBitString.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/pkcs/RSAESOAEPparams.cs b/crypto/src/asn1/pkcs/RSAESOAEPparams.cs
index 3490509e7..1ce8c7daf 100644
--- a/crypto/src/asn1/pkcs/RSAESOAEPparams.cs
+++ b/crypto/src/asn1/pkcs/RSAESOAEPparams.cs
@@ -43,13 +43,13 @@ namespace Org.BouncyCastle.Asn1.Pkcs
             if (count < 0 || count > 3)
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-			m_hashAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, AlgorithmIdentifier.GetInstance)
+			m_hashAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, AlgorithmIdentifier.GetTagged)
 				?? DefaultHashAlgorithm;
 
-            m_maskGenAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, AlgorithmIdentifier.GetInstance)
+            m_maskGenAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, AlgorithmIdentifier.GetTagged)
                 ?? DefaultMaskGenAlgorithm;
 
-            m_pSourceAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, AlgorithmIdentifier.GetInstance)
+            m_pSourceAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, AlgorithmIdentifier.GetTagged)
                 ?? DefaultPSourceAlgorithm;
 
             if (pos != count)
diff --git a/crypto/src/asn1/pkcs/RSASSAPSSparams.cs b/crypto/src/asn1/pkcs/RSASSAPSSparams.cs
index f7a9d6956..7f38cd73f 100644
--- a/crypto/src/asn1/pkcs/RSASSAPSSparams.cs
+++ b/crypto/src/asn1/pkcs/RSASSAPSSparams.cs
@@ -45,16 +45,16 @@ namespace Org.BouncyCastle.Asn1.Pkcs
             if (count < 0 || count > 4)
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-            m_hashAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, AlgorithmIdentifier.GetInstance)
+            m_hashAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, AlgorithmIdentifier.GetTagged)
                 ?? DefaultHashAlgorithm;
 
-            m_maskGenAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, AlgorithmIdentifier.GetInstance)
+            m_maskGenAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, AlgorithmIdentifier.GetTagged)
                 ?? DefaultMaskGenAlgorithm;
 
-            m_saltLength = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, DerInteger.GetInstance)
+            m_saltLength = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, DerInteger.GetTagged)
                 ?? DefaultSaltLength;
 
-            m_trailerField = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 3, true, DerInteger.GetInstance)
+            m_trailerField = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 3, true, DerInteger.GetTagged)
                 ?? DefaultTrailerField;
 
             if (pos != count)
diff --git a/crypto/src/asn1/pkcs/SignedData.cs b/crypto/src/asn1/pkcs/SignedData.cs
index de9c758fb..77f9d00dc 100644
--- a/crypto/src/asn1/pkcs/SignedData.cs
+++ b/crypto/src/asn1/pkcs/SignedData.cs
@@ -38,8 +38,8 @@ namespace Org.BouncyCastle.Asn1.Pkcs
             m_version = DerInteger.GetInstance(seq[pos++]);
             m_digestAlgorithms = Asn1Set.GetInstance(seq[pos++]);
             m_contentInfo = ContentInfo.GetInstance(seq[pos++]);
-            m_certificates = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetInstance);
-            m_crls = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetInstance);
+            m_certificates = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetTagged);
+            m_crls = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetTagged);
             m_signerInfos = Asn1Set.GetInstance(seq[pos++]);
 
             if (pos != count)
diff --git a/crypto/src/asn1/pkcs/SignerInfo.cs b/crypto/src/asn1/pkcs/SignerInfo.cs
index 01d9de98e..8f2e94983 100644
--- a/crypto/src/asn1/pkcs/SignerInfo.cs
+++ b/crypto/src/asn1/pkcs/SignerInfo.cs
@@ -46,10 +46,10 @@ namespace Org.BouncyCastle.Asn1.Pkcs
             m_version = DerInteger.GetInstance(seq[pos++]);
             m_issuerAndSerialNumber = IssuerAndSerialNumber.GetInstance(seq[pos++]);
             m_digAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]);
-            m_authenticatedAttributes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetInstance);
+            m_authenticatedAttributes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetTagged);
             m_digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]);
             m_encryptedDigest = Asn1OctetString.GetInstance(seq[pos++]);
-            m_unauthenticatedAttributes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetInstance);
+            m_unauthenticatedAttributes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetTagged);
 
             if (pos != count)
                 throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
diff --git a/crypto/src/asn1/x500/DirectoryString.cs b/crypto/src/asn1/x500/DirectoryString.cs
index 154e4940e..a04ed0056 100644
--- a/crypto/src/asn1/x500/DirectoryString.cs
+++ b/crypto/src/asn1/x500/DirectoryString.cs
@@ -29,12 +29,13 @@ namespace Org.BouncyCastle.Asn1.X500
             throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj");
 		}
 
-        public static DirectoryString GetInstance(Asn1TaggedObject obj, bool isExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(obj, isExplicit, GetInstance);
-        }
+        public static DirectoryString GetInstance(Asn1TaggedObject obj, bool isExplicit) =>
+            Asn1Utilities.GetInstanceChoice(obj, isExplicit, GetInstance);
 
-		private DirectoryString(
+        public static DirectoryString GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
+
+        private DirectoryString(
 			DerStringBase str)
 		{
 			this.str = str;
diff --git a/crypto/src/asn1/x509/AlgorithmIdentifier.cs b/crypto/src/asn1/x509/AlgorithmIdentifier.cs
index f73401b63..e46b22e4c 100644
--- a/crypto/src/asn1/x509/AlgorithmIdentifier.cs
+++ b/crypto/src/asn1/x509/AlgorithmIdentifier.cs
@@ -17,10 +17,8 @@ namespace Org.BouncyCastle.Asn1.X509
             return new AlgorithmIdentifier(Asn1Sequence.GetInstance(obj));
         }
 
-        public static AlgorithmIdentifier GetInstance(Asn1TaggedObject obj, bool explicitly)
-        {
-            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
-        }
+        public static AlgorithmIdentifier GetInstance(Asn1TaggedObject obj, bool explicitly) =>
+            new AlgorithmIdentifier(Asn1Sequence.GetInstance(obj, explicitly));
 
         public static AlgorithmIdentifier GetOptional(Asn1Encodable element)
         {
@@ -37,6 +35,9 @@ namespace Org.BouncyCastle.Asn1.X509
             return null;
         }
 
+        public static AlgorithmIdentifier GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new AlgorithmIdentifier(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
+
         public AlgorithmIdentifier(
             DerObjectIdentifier algorithm)
         {
diff --git a/crypto/src/asn1/x509/AttCertIssuer.cs b/crypto/src/asn1/x509/AttCertIssuer.cs
index 39ff28790..34116e8a2 100644
--- a/crypto/src/asn1/x509/AttCertIssuer.cs
+++ b/crypto/src/asn1/x509/AttCertIssuer.cs
@@ -36,17 +36,18 @@ namespace Org.BouncyCastle.Asn1.X509
             throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj");
         }
 
-        public static AttCertIssuer GetInstance(Asn1TaggedObject obj, bool isExplicit)
-		{
-            return Asn1Utilities.GetInstanceFromChoice(obj, isExplicit, GetInstance);
-		}
+        public static AttCertIssuer GetInstance(Asn1TaggedObject obj, bool isExplicit) =>
+            Asn1Utilities.GetInstanceChoice(obj, isExplicit, GetInstance);
 
-		/// <summary>
-		/// Don't use this one if you are trying to be RFC 3281 compliant.
-		/// Use it for v1 attribute certificates only.
-		/// </summary>
-		/// <param name="names">Our GeneralNames structure</param>
-		public AttCertIssuer(
+        public static AttCertIssuer GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
+
+        /// <summary>
+        /// Don't use this one if you are trying to be RFC 3281 compliant.
+        /// Use it for v1 attribute certificates only.
+        /// </summary>
+        /// <param name="names">Our GeneralNames structure</param>
+        public AttCertIssuer(
 			GeneralNames names)
 		{
 			obj = names;
diff --git a/crypto/src/asn1/x509/DisplayText.cs b/crypto/src/asn1/x509/DisplayText.cs
index 772e3f522..eb6e6ffe7 100644
--- a/crypto/src/asn1/x509/DisplayText.cs
+++ b/crypto/src/asn1/x509/DisplayText.cs
@@ -151,10 +151,11 @@ namespace Org.BouncyCastle.Asn1.X509
             throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj");
 		}
 
-		public static DisplayText GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-		{
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+		public static DisplayText GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public static DisplayText GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         public override Asn1Object ToAsn1Object()
 		{
diff --git a/crypto/src/asn1/x509/DistributionPointName.cs b/crypto/src/asn1/x509/DistributionPointName.cs
index 1c0455413..274898a3a 100644
--- a/crypto/src/asn1/x509/DistributionPointName.cs
+++ b/crypto/src/asn1/x509/DistributionPointName.cs
@@ -27,10 +27,11 @@ namespace Org.BouncyCastle.Asn1.X509
             return new DistributionPointName(Asn1TaggedObject.GetInstance(obj));
 		}
 
-		public static DistributionPointName GetInstance(Asn1TaggedObject obj, bool explicitly)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(obj, explicitly, GetInstance);
-        }
+		public static DistributionPointName GetInstance(Asn1TaggedObject obj, bool explicitly) =>
+            Asn1Utilities.GetInstanceChoice(obj, explicitly, GetInstance);
+
+        public static DistributionPointName GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         private readonly int m_type;
         private readonly Asn1Encodable m_name;
diff --git a/crypto/src/asn1/x509/GeneralName.cs b/crypto/src/asn1/x509/GeneralName.cs
index 3f5a35d37..08f85bb8e 100644
--- a/crypto/src/asn1/x509/GeneralName.cs
+++ b/crypto/src/asn1/x509/GeneralName.cs
@@ -53,10 +53,11 @@ namespace Org.BouncyCastle.Asn1.X509
 			return GetInstanceSelection(Asn1TaggedObject.GetInstance(obj));
 		}
 
-		public static GeneralName GetInstance(Asn1TaggedObject tagObj, bool explicitly)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(tagObj, explicitly, GetInstance);
-        }
+		public static GeneralName GetInstance(Asn1TaggedObject tagObj, bool explicitly) =>
+            Asn1Utilities.GetInstanceChoice(tagObj, explicitly, GetInstance);
+
+        public static GeneralName GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         private static GeneralName GetInstanceSelection(Asn1TaggedObject taggedObject)
 		{
diff --git a/crypto/src/asn1/x509/GeneralNames.cs b/crypto/src/asn1/x509/GeneralNames.cs
index 3937b3279..40685086e 100644
--- a/crypto/src/asn1/x509/GeneralNames.cs
+++ b/crypto/src/asn1/x509/GeneralNames.cs
@@ -14,10 +14,11 @@ namespace Org.BouncyCastle.Asn1.X509
             return new GeneralNames(Asn1Sequence.GetInstance(obj));
 		}
 
-		public static GeneralNames GetInstance(Asn1TaggedObject obj, bool explicitly)
-		{
-			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
-		}
+		public static GeneralNames GetInstance(Asn1TaggedObject obj, bool explicitly) =>
+			new GeneralNames(Asn1Sequence.GetInstance(obj, explicitly));
+
+        public static GeneralNames GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new GeneralNames(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
 
         public static GeneralNames FromExtensions(X509Extensions extensions, DerObjectIdentifier extOid)
         {
diff --git a/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs b/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs
index fa1fda4ab..c6f4838db 100644
--- a/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs
+++ b/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs
@@ -20,11 +20,27 @@ namespace Org.BouncyCastle.Asn1.X509
             return new SubjectPublicKeyInfo(Asn1Sequence.GetInstance(obj));
         }
 
-        public static SubjectPublicKeyInfo GetInstance(Asn1TaggedObject obj, bool explicitly)
+        public static SubjectPublicKeyInfo GetInstance(Asn1TaggedObject obj, bool explicitly) =>
+            new SubjectPublicKeyInfo(Asn1Sequence.GetInstance(obj, explicitly));
+
+        public static SubjectPublicKeyInfo GetOptional(Asn1Encodable element)
         {
-            return new SubjectPublicKeyInfo(Asn1Sequence.GetInstance(obj, explicitly));
+            if (element == null)
+                throw new ArgumentNullException(nameof(element));
+
+            if (element is SubjectPublicKeyInfo subjectPublicKeyInfo)
+                return subjectPublicKeyInfo;
+
+            Asn1Sequence asn1Sequence = Asn1Sequence.GetOptional(element);
+            if (asn1Sequence != null)
+                return new SubjectPublicKeyInfo(asn1Sequence);
+
+            return null;
         }
 
+        public static SubjectPublicKeyInfo GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new SubjectPublicKeyInfo(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
+
         private readonly AlgorithmIdentifier m_algorithm;
         private readonly DerBitString m_publicKey;
 
diff --git a/crypto/src/asn1/x509/Time.cs b/crypto/src/asn1/x509/Time.cs
index b3a997c33..fba1496f2 100644
--- a/crypto/src/asn1/x509/Time.cs
+++ b/crypto/src/asn1/x509/Time.cs
@@ -22,10 +22,11 @@ namespace Org.BouncyCastle.Asn1.X509
             throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), nameof(obj));
         }
 
-        public static Time GetInstance(Asn1TaggedObject	taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static Time GetInstance(Asn1TaggedObject	taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public static Time GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
 
         public static Time GetOptional(Asn1Encodable element)
         {
diff --git a/crypto/src/asn1/x509/X509Extensions.cs b/crypto/src/asn1/x509/X509Extensions.cs
index 193ac8188..8ab2327d5 100644
--- a/crypto/src/asn1/x509/X509Extensions.cs
+++ b/crypto/src/asn1/x509/X509Extensions.cs
@@ -197,11 +197,6 @@ namespace Org.BouncyCastle.Asn1.X509
         public static Asn1OctetString GetExtensionValue(X509Extensions extensions, DerObjectIdentifier oid) =>
             extensions?.GetExtensionValue(oid);
 
-		public static X509Extensions GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
-        }
-
         public static X509Extensions GetInstance(object obj)
         {
             if (obj == null)
@@ -220,6 +215,9 @@ namespace Org.BouncyCastle.Asn1.X509
             throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), nameof(obj));
         }
 
+        public static X509Extensions GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new X509Extensions(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+
         public static X509Extensions GetOptional(Asn1Encodable element)
         {
             if (element == null)
@@ -235,6 +233,9 @@ namespace Org.BouncyCastle.Asn1.X509
             return null;
         }
 
+        public static X509Extensions GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new X509Extensions(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
+
         /**
          * Constructor from Asn1Sequence.
          *
diff --git a/crypto/src/asn1/x509/X509Name.cs b/crypto/src/asn1/x509/X509Name.cs
index 8f25e49ef..41b0c4cb9 100644
--- a/crypto/src/asn1/x509/X509Name.cs
+++ b/crypto/src/asn1/x509/X509Name.cs
@@ -336,6 +336,9 @@ namespace Org.BouncyCastle.Asn1.X509
         public static X509Name GetInstance(Asn1TaggedObject obj, bool explicitly) =>
             new X509Name(Asn1Sequence.GetInstance(obj, explicitly));
 
+        public static X509Name GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            new X509Name(Asn1Sequence.GetTagged(taggedObject, declaredExplicit));
+
         private readonly List<DerObjectIdentifier> m_ordering = new List<DerObjectIdentifier>();
         private readonly X509NameEntryConverter converter;
 
diff --git a/crypto/src/asn1/x9/X962Parameters.cs b/crypto/src/asn1/x9/X962Parameters.cs
index af1fce1db..e90472a1b 100644
--- a/crypto/src/asn1/x9/X962Parameters.cs
+++ b/crypto/src/asn1/x9/X962Parameters.cs
@@ -35,12 +35,13 @@ namespace Org.BouncyCastle.Asn1.X9
 			throw new ArgumentException("unknown object in GetInstance()");
 		}
 
-        public static X962Parameters GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
-        {
-            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
-        }
+        public static X962Parameters GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance);
 
-		public X962Parameters(
+        public static X962Parameters GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+            Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance);
+
+        public X962Parameters(
             X9ECParameters ecParameters)
         {
             this._params = ecParameters.ToAsn1Object();