summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2023-07-18 12:06:03 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2023-07-18 12:06:03 +0700
commit913eada3ad9394f1327a1feb80a3261f7c6e55bb (patch)
tree6366c1e196ad2ac249edf12a4d41d52ee2d28629
parentRefactoring around PrivateKeyInfo (diff)
downloadBouncyCastle.NET-ed25519-913eada3ad9394f1327a1feb80a3261f7c6e55bb.tar.xz
Deprecated Asn1TaggedObject.GetObject and refactor
-rw-r--r--crypto/src/asn1/Asn1TaggedObject.cs37
-rw-r--r--crypto/src/asn1/DerBitString.cs16
-rw-r--r--crypto/src/asn1/DerObjectIdentifier.cs6
-rw-r--r--crypto/src/asn1/cmp/CertOrEncCert.cs6
-rw-r--r--crypto/src/asn1/cmp/CertifiedKeyPair.cs12
-rw-r--r--crypto/src/asn1/cmp/KeyRecRepContent.cs8
-rw-r--r--crypto/src/asn1/cmp/PKIBody.cs2
-rw-r--r--crypto/src/asn1/cms/ContentInfo.cs4
-rw-r--r--crypto/src/asn1/cms/Evidence.cs4
-rw-r--r--crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs14
-rw-r--r--crypto/src/asn1/cms/Time.cs4
-rw-r--r--crypto/src/asn1/crmf/PKIArchiveOptions.cs24
-rw-r--r--crypto/src/asn1/crmf/PopoSigningKey.cs18
-rw-r--r--crypto/src/asn1/crmf/PopoSigningKeyInput.cs20
-rw-r--r--crypto/src/asn1/esf/CrlOcspRef.cs32
-rw-r--r--crypto/src/asn1/esf/RevocationValues.cs16
-rw-r--r--crypto/src/asn1/esf/SignerLocation.cs4
-rw-r--r--crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs9
-rw-r--r--crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs4
-rw-r--r--crypto/src/asn1/isismtt/x509/ProcurationSyntax.cs8
-rw-r--r--crypto/src/asn1/ocsp/CertStatus.cs5
-rw-r--r--crypto/src/asn1/ocsp/ResponderID.cs20
-rw-r--r--crypto/src/asn1/pkcs/CertBag.cs2
-rw-r--r--crypto/src/asn1/pkcs/ContentInfo.cs2
-rw-r--r--crypto/src/asn1/pkcs/CrlBag.cs2
-rw-r--r--crypto/src/asn1/pkcs/SafeBag.cs2
-rw-r--r--crypto/src/asn1/x500/DirectoryString.cs13
-rw-r--r--crypto/src/asn1/x509/AttCertIssuer.cs6
-rw-r--r--crypto/src/asn1/x509/DisplayText.cs22
-rw-r--r--crypto/src/asn1/x509/Time.cs2
-rw-r--r--crypto/src/asn1/x509/X509Extensions.cs6
-rw-r--r--crypto/src/asn1/x9/OtherInfo.cs8
-rw-r--r--crypto/src/asn1/x9/X962Parameters.cs29
33 files changed, 171 insertions, 196 deletions
diff --git a/crypto/src/asn1/Asn1TaggedObject.cs b/crypto/src/asn1/Asn1TaggedObject.cs
index ea882f31d..58566694b 100644
--- a/crypto/src/asn1/Asn1TaggedObject.cs
+++ b/crypto/src/asn1/Asn1TaggedObject.cs
@@ -223,13 +223,12 @@ namespace Org.BouncyCastle.Asn1
             }
         }
 
-        /**
-         * return whatever was following the tag.
-         * <p>
-         * Note: tagged objects are generally context dependent if you're
-         * trying to extract a tagged object you should be going via the
-         * appropriate GetInstance method.</p>
-         */
+        /// <summary>Return whatever was following the tag.</summary>
+        /// <remarks>
+        /// Tagged objects are generally context dependent. If you're trying to extract a tagged object you should be
+        /// going via the appropriate GetInstance method.
+        /// </remarks>
+        [Obsolete("Will be removed")]
         public Asn1Object GetObject()
         {
             Asn1Utilities.CheckTagClass(this, Asn1Tags.ContextSpecific);
@@ -237,23 +236,23 @@ namespace Org.BouncyCastle.Asn1
             return m_object.ToAsn1Object();
         }
 
-        /**
-         * Needed for open types, until we have better type-guided parsing support. Use sparingly for other
-         * purposes, and prefer {@link #getExplicitBaseTagged()}, {@link #getImplicitBaseTagged(int, int)} or
-         * {@link #getBaseUniversal(boolean, int)} where possible. Before using, check for matching tag
-         * {@link #getTagClass() class} and {@link #getTagNo() number}.
-         */
+        /// <summary>Needed for open types, until we have better type-guided parsing support.</summary>
+        /// <remarks>
+        /// Use sparingly for other purposes, and prefer <see cref="GetExplicitBaseTagged"/>,
+        /// <see cref="GetImplicitBaseTagged(int, int)"/> or <see cref="GetBaseUniversal(bool, int)"/> where possible.
+        /// Before using, check for matching tag <see cref="TagClass">class</see> and <see cref="TagNo">number</see>.
+        /// </remarks>
         public Asn1Encodable GetBaseObject()
         {
             return m_object;
         }
 
-        /**
-         * Needed for open types, until we have better type-guided parsing support. Use
-         * sparingly for other purposes, and prefer {@link #getExplicitBaseTagged()} or
-         * {@link #getBaseUniversal(boolean, int)} where possible. Before using, check
-         * for matching tag {@link #getTagClass() class} and {@link #getTagNo() number}.
-         */
+        /// <summary>Needed for open types, until we have better type-guided parsing support.</summary>
+        /// <remarks>
+        /// Use sparingly for other purposes, and prefer <see cref="GetExplicitBaseTagged"/> or
+        /// <see cref="GetBaseUniversal(bool, int)"/> where possible. Before using, check for matching tag
+        /// <see cref="TagClass">class</see> and <see cref="TagNo">number</see>.
+        /// </remarks>
         public Asn1Encodable GetExplicitBaseObject()
         {
             if (!IsExplicit())
diff --git a/crypto/src/asn1/DerBitString.cs b/crypto/src/asn1/DerBitString.cs
index bc3de7fe4..caa97933f 100644
--- a/crypto/src/asn1/DerBitString.cs
+++ b/crypto/src/asn1/DerBitString.cs
@@ -74,18 +74,10 @@ namespace Org.BouncyCastle.Asn1
 		 * @exception ArgumentException if the tagged object cannot
 		 *               be converted.
 		 */
-		public static DerBitString GetInstance(Asn1TaggedObject obj, bool isExplicit)
-		{
-			Asn1Object o = obj.GetObject();
-
-			if (isExplicit || o is DerBitString)
-			{
-				return GetInstance(o);
-			}
-
-            // Not copied because assumed to be a tagged implicit primitive from the parser
-			return CreatePrimitive(((Asn1OctetString)o).GetOctets());
-		}
+        public static DerBitString GetInstance(Asn1TaggedObject obj, bool isExplicit)
+        {
+            return (DerBitString)Meta.Instance.GetContextInstance(obj, isExplicit);
+        }
 
         internal readonly byte[] contents;
 
diff --git a/crypto/src/asn1/DerObjectIdentifier.cs b/crypto/src/asn1/DerObjectIdentifier.cs
index 835f18d3d..91e427d0b 100644
--- a/crypto/src/asn1/DerObjectIdentifier.cs
+++ b/crypto/src/asn1/DerObjectIdentifier.cs
@@ -65,13 +65,13 @@ namespace Org.BouncyCastle.Asn1
         public static DerObjectIdentifier GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
         {
             /*
-             * TODO[asn1] This block here is for backward compatibility, but should eventually be removed.
+             * TODO[api] This block is for backward compatibility, but should be removed.
              * 
              * - see https://github.com/bcgit/bc-java/issues/1015
              */
-            if (!declaredExplicit && !taggedObject.IsParsed())
+            if (!declaredExplicit && !taggedObject.IsParsed() && Asn1Tags.ContextSpecific == taggedObject.TagClass)
             {
-                Asn1Object baseObject = taggedObject.GetObject();
+                Asn1Object baseObject = taggedObject.GetBaseObject().ToAsn1Object();
                 if (!(baseObject is DerObjectIdentifier))
                     return FromContents(Asn1OctetString.GetInstance(baseObject).GetOctets());
             }
diff --git a/crypto/src/asn1/cmp/CertOrEncCert.cs b/crypto/src/asn1/cmp/CertOrEncCert.cs
index 1423503d2..d248de1aa 100644
--- a/crypto/src/asn1/cmp/CertOrEncCert.cs
+++ b/crypto/src/asn1/cmp/CertOrEncCert.cs
@@ -13,7 +13,7 @@ namespace Org.BouncyCastle.Asn1.Cmp
 				return null;
             if (obj is CertOrEncCert certOrEncCert)
                 return certOrEncCert;
-            return new CertOrEncCert(Asn1TaggedObject.GetInstance(obj));
+            return new CertOrEncCert(Asn1TaggedObject.GetInstance(obj, Asn1Tags.ContextSpecific));
         }
 
         public static CertOrEncCert GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
@@ -28,11 +28,11 @@ namespace Org.BouncyCastle.Asn1.Cmp
 		{
 			if (taggedObject.TagNo == 0)
 			{
-				m_certificate = CmpCertificate.GetInstance(taggedObject.GetObject());
+				m_certificate = CmpCertificate.GetInstance(taggedObject.GetExplicitBaseObject());
 			}
 			else if (taggedObject.TagNo == 1)
 			{
-                m_encryptedCert = EncryptedKey.GetInstance(taggedObject.GetObject());
+                m_encryptedCert = EncryptedKey.GetInstance(taggedObject.GetExplicitBaseObject());
 			}
 			else
 			{
diff --git a/crypto/src/asn1/cmp/CertifiedKeyPair.cs b/crypto/src/asn1/cmp/CertifiedKeyPair.cs
index e26c5c629..73828fda4 100644
--- a/crypto/src/asn1/cmp/CertifiedKeyPair.cs
+++ b/crypto/src/asn1/cmp/CertifiedKeyPair.cs
@@ -33,20 +33,22 @@ namespace Org.BouncyCastle.Asn1.Cmp
 			{
 				if (seq.Count == 2)
 				{
-					Asn1TaggedObject tagged = Asn1TaggedObject.GetInstance(seq[1]);
+					Asn1TaggedObject tagged = Asn1TaggedObject.GetInstance(seq[1], Asn1Tags.ContextSpecific);
 					if (tagged.TagNo == 0)
 					{
-						m_privateKey = EncryptedKey.GetInstance(tagged.GetObject());
+						m_privateKey = EncryptedKey.GetInstance(tagged.GetExplicitBaseObject());
 					}
 					else
 					{
-						m_publicationInfo = PkiPublicationInfo.GetInstance(tagged.GetObject());
+						m_publicationInfo = PkiPublicationInfo.GetInstance(tagged.GetExplicitBaseObject());
 					}
 				}
 				else
 				{
-                    m_privateKey = EncryptedKey.GetInstance(Asn1TaggedObject.GetInstance(seq[1]).GetObject());
-                    m_publicationInfo = PkiPublicationInfo.GetInstance(Asn1TaggedObject.GetInstance(seq[2]).GetObject());
+                    m_privateKey = EncryptedKey.GetInstance(
+						Asn1TaggedObject.GetInstance(seq[1], Asn1Tags.ContextSpecific).GetExplicitBaseObject());
+                    m_publicationInfo = PkiPublicationInfo.GetInstance(
+						Asn1TaggedObject.GetInstance(seq[2], Asn1Tags.ContextSpecific).GetExplicitBaseObject());
 				}
 			}
 		}
diff --git a/crypto/src/asn1/cmp/KeyRecRepContent.cs b/crypto/src/asn1/cmp/KeyRecRepContent.cs
index 880eb9895..8121988d2 100644
--- a/crypto/src/asn1/cmp/KeyRecRepContent.cs
+++ b/crypto/src/asn1/cmp/KeyRecRepContent.cs
@@ -30,18 +30,18 @@ namespace Org.BouncyCastle.Asn1.Cmp
 
 			for (int pos = 1; pos < seq.Count; ++pos)
 			{
-				Asn1TaggedObject tObj = Asn1TaggedObject.GetInstance(seq[pos]);
+				Asn1TaggedObject tObj = Asn1TaggedObject.GetInstance(seq[pos], Asn1Tags.ContextSpecific);
 
 				switch (tObj.TagNo)
 				{
 				case 0:
-					m_newSigCert = CmpCertificate.GetInstance(tObj.GetObject());
+					m_newSigCert = CmpCertificate.GetInstance(tObj.GetExplicitBaseObject());
 					break;
 				case 1:
-					m_caCerts = Asn1Sequence.GetInstance(tObj.GetObject());
+					m_caCerts = Asn1Sequence.GetInstance(tObj.GetExplicitBaseObject());
 					break;
 				case 2:
-					m_keyPairHist = Asn1Sequence.GetInstance(tObj.GetObject());
+					m_keyPairHist = Asn1Sequence.GetInstance(tObj.GetExplicitBaseObject());
 					break;
 				default:
 					throw new ArgumentException("unknown tag number: " + tObj.TagNo, "seq");
diff --git a/crypto/src/asn1/cmp/PKIBody.cs b/crypto/src/asn1/cmp/PKIBody.cs
index 2a92053b5..467a78c8d 100644
--- a/crypto/src/asn1/cmp/PKIBody.cs
+++ b/crypto/src/asn1/cmp/PKIBody.cs
@@ -87,7 +87,7 @@ namespace Org.BouncyCastle.Asn1.Cmp
         private PkiBody(Asn1TaggedObject taggedObject)
         {
             m_tagNo = taggedObject.TagNo;
-            m_body = GetBodyForType(m_tagNo, taggedObject.GetObject());
+            m_body = GetBodyForType(m_tagNo, taggedObject.GetExplicitBaseObject());
         }
 
         /**
diff --git a/crypto/src/asn1/cms/ContentInfo.cs b/crypto/src/asn1/cms/ContentInfo.cs
index 847df6dd8..c8f9fc65b 100644
--- a/crypto/src/asn1/cms/ContentInfo.cs
+++ b/crypto/src/asn1/cms/ContentInfo.cs
@@ -37,11 +37,11 @@ namespace Org.BouncyCastle.Asn1.Cms
 
             if (seq.Count > 1)
             {
-                Asn1TaggedObject tagged = (Asn1TaggedObject) seq[1];
+                Asn1TaggedObject tagged = Asn1TaggedObject.GetInstance(seq[1], Asn1Tags.ContextSpecific);
                 if (!tagged.IsExplicit() || tagged.TagNo != 0)
                     throw new ArgumentException("Bad tag for 'content'", "seq");
 
-                content = tagged.GetObject();
+                content = tagged.GetExplicitBaseObject();
             }
         }
 
diff --git a/crypto/src/asn1/cms/Evidence.cs b/crypto/src/asn1/cms/Evidence.cs
index 2e39054d6..54d498cb9 100644
--- a/crypto/src/asn1/cms/Evidence.cs
+++ b/crypto/src/asn1/cms/Evidence.cs
@@ -41,14 +41,14 @@ namespace Org.BouncyCastle.Asn1.Cms
 				return evidence;
 
 			if (obj is Asn1TaggedObject taggedObject)
-				return new Evidence(taggedObject);
+				return new Evidence(Asn1Utilities.CheckTagClass(taggedObject, Asn1Tags.ContextSpecific));
 
 			throw new ArgumentException("Unknown object in GetInstance: " + Platform.GetTypeName(obj), "obj");
 		}
 
         public static Evidence GetInstance(Asn1TaggedObject obj, bool isExplicit)
         {
-            return GetInstance(obj.GetObject()); // must be explicitly tagged
+            return Asn1Utilities.GetInstanceFromChoice(obj, isExplicit, GetInstance);
         }
 
 		public virtual TimeStampTokenEvidence TstEvidence
diff --git a/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs b/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs
index 01c5a31a1..6b4c0488e 100644
--- a/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs
+++ b/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs
@@ -40,17 +40,9 @@ namespace Org.BouncyCastle.Asn1.Cms
          * @exception ArgumentException if the object held by the
          *          tagged object cannot be converted.
          */
-        public static OriginatorIdentifierOrKey GetInstance(
-            Asn1TaggedObject	o,
-            bool				explicitly)
+        public static OriginatorIdentifierOrKey GetInstance(Asn1TaggedObject o, bool explicitly)
         {
-            if (!explicitly)
-            {
-                throw new ArgumentException(
-                        "Can't implicitly tag OriginatorIdentifierOrKey");
-            }
-
-			return GetInstance(o.GetObject());
+            return Asn1Utilities.GetInstanceFromChoice(o, explicitly, GetInstance);
         }
 
         /**
@@ -78,7 +70,7 @@ namespace Org.BouncyCastle.Asn1.Cms
 				return new OriginatorIdentifierOrKey(originatorPublicKey);
 
 			if (o is Asn1TaggedObject taggedObject)
-				return new OriginatorIdentifierOrKey(taggedObject);
+				return new OriginatorIdentifierOrKey(Asn1Utilities.CheckTagClass(taggedObject, Asn1Tags.ContextSpecific));
 
             throw new ArgumentException("Invalid OriginatorIdentifierOrKey: " + Platform.GetTypeName(o));
         }
diff --git a/crypto/src/asn1/cms/Time.cs b/crypto/src/asn1/cms/Time.cs
index 19bc1a633..f41433ddd 100644
--- a/crypto/src/asn1/cms/Time.cs
+++ b/crypto/src/asn1/cms/Time.cs
@@ -22,9 +22,9 @@ 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)
+        public static Time GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
         {
-            return GetInstance(taggedObject.GetObject());
+            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
         }
 
         private readonly Asn1Object m_timeObject;
diff --git a/crypto/src/asn1/crmf/PKIArchiveOptions.cs b/crypto/src/asn1/crmf/PKIArchiveOptions.cs
index e546fb3bb..f1a35541a 100644
--- a/crypto/src/asn1/crmf/PKIArchiveOptions.cs
+++ b/crypto/src/asn1/crmf/PKIArchiveOptions.cs
@@ -19,7 +19,7 @@ namespace Org.BouncyCastle.Asn1.Crmf
                 return pkiArchiveOptions;
 
             if (obj is Asn1TaggedObject taggedObject)
-                return new PkiArchiveOptions(taggedObject);
+                return new PkiArchiveOptions(Asn1Utilities.CheckTagClass(taggedObject, Asn1Tags.ContextSpecific));
 
             throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), "obj");
         }
@@ -28,17 +28,17 @@ namespace Org.BouncyCastle.Asn1.Crmf
         {
             switch (tagged.TagNo)
             {
-                case encryptedPrivKey:
-                    value = EncryptedKey.GetInstance(tagged.GetObject());
-                    break;
-                case keyGenParameters:
-                    value = Asn1OctetString.GetInstance(tagged, false);
-                    break;
-                case archiveRemGenPrivKey:
-                    value = DerBoolean.GetInstance(tagged, false);
-                    break;
-                default:
-                    throw new ArgumentException("unknown tag number: " + tagged.TagNo, "tagged");
+            case encryptedPrivKey:
+                value = EncryptedKey.GetInstance(tagged.GetExplicitBaseObject());
+                break;
+            case keyGenParameters:
+                value = Asn1OctetString.GetInstance(tagged, false);
+                break;
+            case archiveRemGenPrivKey:
+                value = DerBoolean.GetInstance(tagged, false);
+                break;
+            default:
+                throw new ArgumentException("unknown tag number: " + tagged.TagNo, "tagged");
             }
         }
 
diff --git a/crypto/src/asn1/crmf/PopoSigningKey.cs b/crypto/src/asn1/crmf/PopoSigningKey.cs
index caa226b56..c4b0594f7 100644
--- a/crypto/src/asn1/crmf/PopoSigningKey.cs
+++ b/crypto/src/asn1/crmf/PopoSigningKey.cs
@@ -20,10 +20,8 @@ namespace Org.BouncyCastle.Asn1.Crmf
             {
                 index++;
 
-                if (tagObj.TagNo != 0)
-                    throw new ArgumentException( "Unknown PopoSigningKeyInput tag: " + tagObj.TagNo, nameof(seq));
-
-                poposkInput = PopoSigningKeyInput.GetInstance(tagObj.GetObject());
+                poposkInput = PopoSigningKeyInput.GetInstance(
+                    Asn1Utilities.GetContextBaseUniversal(tagObj, 0, false, Asn1Tags.Sequence));
             }
             algorithmIdentifier = AlgorithmIdentifier.GetInstance(seq[index++]);
             signature = DerBitString.GetInstance(seq[index]);
@@ -31,13 +29,11 @@ namespace Org.BouncyCastle.Asn1.Crmf
 
         public static PopoSigningKey GetInstance(object obj)
         {
-            if (obj is PopoSigningKey)
-                return (PopoSigningKey)obj;
-
-            if (obj is Asn1Sequence)
-                return new PopoSigningKey((Asn1Sequence)obj);
-
-            throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), "obj");
+            if (obj == null)
+                return null;
+            if (obj is PopoSigningKey popoSigningKey)
+                return popoSigningKey;
+            return new PopoSigningKey(Asn1Sequence.GetInstance(obj));
         }
 
         public static PopoSigningKey GetInstance(Asn1TaggedObject obj, bool isExplicit)
diff --git a/crypto/src/asn1/crmf/PopoSigningKeyInput.cs b/crypto/src/asn1/crmf/PopoSigningKeyInput.cs
index f2517aa57..2853e9486 100644
--- a/crypto/src/asn1/crmf/PopoSigningKeyInput.cs
+++ b/crypto/src/asn1/crmf/PopoSigningKeyInput.cs
@@ -18,10 +18,7 @@ namespace Org.BouncyCastle.Asn1.Crmf
 
             if (authInfo is Asn1TaggedObject tagObj)
             {
-                if (tagObj.TagNo != 0)
-                    throw new ArgumentException("Unknown authInfo tag: " + tagObj.TagNo, nameof(seq));
-
-                sender = GeneralName.GetInstance(tagObj.GetObject());
+                sender = GeneralName.GetInstance(Asn1Utilities.GetExplicitContextBaseObject(tagObj, 0));
             }
             else
             {
@@ -33,13 +30,16 @@ namespace Org.BouncyCastle.Asn1.Crmf
 
         public static PopoSigningKeyInput GetInstance(object obj)
         {
-            if (obj is PopoSigningKeyInput)
-                return (PopoSigningKeyInput)obj;
-
-            if (obj is Asn1Sequence)
-                return new PopoSigningKeyInput((Asn1Sequence)obj);
+            if (obj == null)
+                return null;
+            if (obj is PopoSigningKeyInput popoSigningKeyInput)
+                return popoSigningKeyInput;
+            return new PopoSigningKeyInput(Asn1Sequence.GetInstance(obj));
+        }
 
-            throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), "obj");
+        public static PopoSigningKeyInput GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         /** Creates a new PopoSigningKeyInput with sender name as authInfo. */
diff --git a/crypto/src/asn1/esf/CrlOcspRef.cs b/crypto/src/asn1/esf/CrlOcspRef.cs
index 6f55ff057..3b7598c9f 100644
--- a/crypto/src/asn1/esf/CrlOcspRef.cs
+++ b/crypto/src/asn1/esf/CrlOcspRef.cs
@@ -36,29 +36,27 @@ namespace Org.BouncyCastle.Asn1.Esf
 				"obj");
 		}
 
-		private CrlOcspRef(
-			Asn1Sequence seq)
+		private CrlOcspRef(Asn1Sequence seq)
 		{
 			if (seq == null)
 				throw new ArgumentNullException("seq");
 
-			foreach (Asn1TaggedObject taggedObj in seq)
+			foreach (var element in seq)
 			{
-				Asn1Object asn1Obj = taggedObj.GetObject();
-
-				switch (taggedObj.TagNo)
+				var o = Asn1TaggedObject.GetInstance(element, Asn1Tags.ContextSpecific);
+				switch (o.TagNo)
 				{
-					case 0:
-						this.crlids = CrlListID.GetInstance(asn1Obj);
-						break;
-					case 1:
-						this.ocspids = OcspListID.GetInstance(asn1Obj);
-						break;
-					case 2:
-						this.otherRev = OtherRevRefs.GetInstance(asn1Obj);
-						break;
-					default:
-						throw new ArgumentException("Illegal tag in CrlOcspRef", "seq");
+				case 0:
+					this.crlids = CrlListID.GetInstance(o.GetExplicitBaseObject());
+					break;
+				case 1:
+					this.ocspids = OcspListID.GetInstance(o.GetExplicitBaseObject());
+					break;
+				case 2:
+					this.otherRev = OtherRevRefs.GetInstance(o.GetExplicitBaseObject());
+					break;
+				default:
+					throw new ArgumentException("Illegal tag in CrlOcspRef", "seq");
 				}
 			}
 		}
diff --git a/crypto/src/asn1/esf/RevocationValues.cs b/crypto/src/asn1/esf/RevocationValues.cs
index f3b36f1d1..497bf15f2 100644
--- a/crypto/src/asn1/esf/RevocationValues.cs
+++ b/crypto/src/asn1/esf/RevocationValues.cs
@@ -41,29 +41,29 @@ namespace Org.BouncyCastle.Asn1.Esf
 			if (seq.Count > 3)
 				throw new ArgumentException("Bad sequence size: " + seq.Count, nameof(seq));
 
-			foreach (Asn1TaggedObject taggedObj in seq)
+			foreach (var element in seq)
 			{
-				Asn1Object asn1Obj = taggedObj.GetObject();
-				switch (taggedObj.TagNo)
+				var o = Asn1TaggedObject.GetInstance(element, Asn1Tags.ContextSpecific);
+				switch (o.TagNo)
 				{
 				case 0:
-					Asn1Sequence crlValsSeq = (Asn1Sequence)asn1Obj;
+					Asn1Sequence crlValsSeq = (Asn1Sequence)o.GetExplicitBaseObject();
 
 					// Validate
-					crlValsSeq.MapElements(element => CertificateList.GetInstance(element.ToAsn1Object()));
+					crlValsSeq.MapElements(CertificateList.GetInstance);
 
 					m_crlVals = crlValsSeq;
 					break;
 				case 1:
-					Asn1Sequence ocspValsSeq = (Asn1Sequence)asn1Obj;
+					Asn1Sequence ocspValsSeq = (Asn1Sequence)o.GetExplicitBaseObject();
 
 					// Validate
-					ocspValsSeq.MapElements(element => BasicOcspResponse.GetInstance(element.ToAsn1Object()));
+					ocspValsSeq.MapElements(BasicOcspResponse.GetInstance);
 
 					m_ocspVals = ocspValsSeq;
 					break;
 				case 2:
-					m_otherRevVals = OtherRevVals.GetInstance(asn1Obj);
+					m_otherRevVals = OtherRevVals.GetInstance(o.GetExplicitBaseObject());
 					break;
 				default:
 					throw new ArgumentException("Illegal tag in RevocationValues", nameof(seq));
diff --git a/crypto/src/asn1/esf/SignerLocation.cs b/crypto/src/asn1/esf/SignerLocation.cs
index 106a32c59..7b1300045 100644
--- a/crypto/src/asn1/esf/SignerLocation.cs
+++ b/crypto/src/asn1/esf/SignerLocation.cs
@@ -25,8 +25,10 @@ namespace Org.BouncyCastle.Asn1.Esf
 
 		public SignerLocation(Asn1Sequence seq)
 		{
-			foreach (Asn1TaggedObject obj in seq)
+			foreach (var element in seq)
 			{
+				var obj = Asn1TaggedObject.GetInstance(element, Asn1Tags.ContextSpecific);
+
 				switch (obj.TagNo)
 				{
 				case 0:
diff --git a/crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs b/crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs
index 0348b0916..e2de8882d 100644
--- a/crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs
+++ b/crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs
@@ -70,14 +70,9 @@ 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)
+		public static RequestedCertificate GetInstance(Asn1TaggedObject obj, bool isExplicit)
 		{
-			if (!isExplicit)
-				throw new ArgumentException("choice item must be explicitly tagged");
-
-			return GetInstance(obj.GetObject());
+			return Asn1Utilities.GetInstanceFromChoice(obj, isExplicit, GetInstance);
 		}
 
 		private RequestedCertificate(
diff --git a/crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs b/crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs
index 471776630..f20d17f6b 100644
--- a/crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs
+++ b/crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs
@@ -73,8 +73,8 @@ namespace Org.BouncyCastle.Asn1.IsisMtt.X509
 			if (obj is DeclarationOfMajority declarationOfMajority)
 				return declarationOfMajority;
 
-			if (obj is Asn1TaggedObject asn1TaggedObject)
-				return new DeclarationOfMajority(asn1TaggedObject);
+			if (obj is Asn1TaggedObject taggedObject)
+				return new DeclarationOfMajority(Asn1Utilities.CheckTagClass(taggedObject, Asn1Tags.ContextSpecific));
 
             throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), nameof(obj));
 		}
diff --git a/crypto/src/asn1/isismtt/x509/ProcurationSyntax.cs b/crypto/src/asn1/isismtt/x509/ProcurationSyntax.cs
index 2fb7323c6..96047f9bd 100644
--- a/crypto/src/asn1/isismtt/x509/ProcurationSyntax.cs
+++ b/crypto/src/asn1/isismtt/x509/ProcurationSyntax.cs
@@ -85,11 +85,9 @@ namespace Org.BouncyCastle.Asn1.IsisMtt.X509
 			if (seq.Count < 1 || seq.Count > 3)
 				throw new ArgumentException("Bad sequence size: " + seq.Count);
 
-			var e = seq.GetEnumerator();
-
-			while (e.MoveNext())
+			foreach (var element in seq)
 			{
-				Asn1TaggedObject o = Asn1TaggedObject.GetInstance(e.Current);
+				Asn1TaggedObject o = Asn1TaggedObject.GetInstance(element, Asn1Tags.ContextSpecific);
 				switch (o.TagNo)
 				{
 				case 1:
@@ -99,7 +97,7 @@ namespace Org.BouncyCastle.Asn1.IsisMtt.X509
 					typeOfSubstitution = DirectoryString.GetInstance(o, true);
 					break;
 				case 3:
-					Asn1Object signingFor = o.GetObject();
+					Asn1Encodable signingFor = o.GetExplicitBaseObject();
 					if (signingFor is Asn1TaggedObject)
 					{
 						thirdPerson = GeneralName.GetInstance(signingFor);
diff --git a/crypto/src/asn1/ocsp/CertStatus.cs b/crypto/src/asn1/ocsp/CertStatus.cs
index 65f11fc7f..18b7bd21c 100644
--- a/crypto/src/asn1/ocsp/CertStatus.cs
+++ b/crypto/src/asn1/ocsp/CertStatus.cs
@@ -68,6 +68,11 @@ namespace Org.BouncyCastle.Asn1.Ocsp
             throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj");
         }
 
+        public static CertStatus GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
+        }
+
         public int TagNo
 		{
 			get { return tagNo; }
diff --git a/crypto/src/asn1/ocsp/ResponderID.cs b/crypto/src/asn1/ocsp/ResponderID.cs
index bc8b7f731..d677e63b0 100644
--- a/crypto/src/asn1/ocsp/ResponderID.cs
+++ b/crypto/src/asn1/ocsp/ResponderID.cs
@@ -33,7 +33,12 @@ namespace Org.BouncyCastle.Asn1.Ocsp
 			return new ResponderID(X509Name.GetInstance(obj));
 		}
 
-		public ResponderID(
+        public static ResponderID GetInstance(Asn1TaggedObject obj, bool isExplicit)
+        {
+            return Asn1Utilities.GetInstanceFromChoice(obj, isExplicit, GetInstance);
+        }
+
+        public ResponderID(
             Asn1OctetString id)
         {
 			if (id == null)
@@ -51,19 +56,10 @@ namespace Org.BouncyCastle.Asn1.Ocsp
 			this.id = id;
         }
 
-		public static ResponderID GetInstance(
-			Asn1TaggedObject	obj,
-			bool				isExplicit)
-		{
-			return GetInstance(obj.GetObject()); // must be explicitly tagged
-		}
-
 		public virtual byte[] GetKeyHash()
 		{
-			if (id is Asn1OctetString)
-			{
-				return ((Asn1OctetString)id).GetOctets();
-			}
+			if (id is Asn1OctetString octetString)
+				return octetString.GetOctets();
 
 			return null;
 		}
diff --git a/crypto/src/asn1/pkcs/CertBag.cs b/crypto/src/asn1/pkcs/CertBag.cs
index 81868fef6..129a73ada 100644
--- a/crypto/src/asn1/pkcs/CertBag.cs
+++ b/crypto/src/asn1/pkcs/CertBag.cs
@@ -23,7 +23,7 @@ namespace Org.BouncyCastle.Asn1.Pkcs
 				throw new ArgumentException("Wrong number of elements in sequence", nameof(seq));
 
             this.m_certID = DerObjectIdentifier.GetInstance(seq[0]);
-            this.m_certValue = Asn1TaggedObject.GetInstance(seq[1]).GetObject();
+            this.m_certValue = Asn1TaggedObject.GetInstance(seq[1]).GetExplicitBaseObject().ToAsn1Object();
         }
 
 		public CertBag(DerObjectIdentifier certID, Asn1Object certValue)
diff --git a/crypto/src/asn1/pkcs/ContentInfo.cs b/crypto/src/asn1/pkcs/ContentInfo.cs
index 05d9a2033..0a19306f2 100644
--- a/crypto/src/asn1/pkcs/ContentInfo.cs
+++ b/crypto/src/asn1/pkcs/ContentInfo.cs
@@ -22,7 +22,7 @@ namespace Org.BouncyCastle.Asn1.Pkcs
 
             if (seq.Count > 1)
             {
-                content = ((Asn1TaggedObject) seq[1]).GetObject();
+                content = ((Asn1TaggedObject) seq[1]).GetExplicitBaseObject();
             }
         }
 
diff --git a/crypto/src/asn1/pkcs/CrlBag.cs b/crypto/src/asn1/pkcs/CrlBag.cs
index 5cc68ace4..0198c341c 100644
--- a/crypto/src/asn1/pkcs/CrlBag.cs
+++ b/crypto/src/asn1/pkcs/CrlBag.cs
@@ -23,7 +23,7 @@ namespace Org.BouncyCastle.Asn1.Pkcs
                 throw new ArgumentException("Wrong number of elements in sequence", nameof(seq));
 
             m_crlID = DerObjectIdentifier.GetInstance(seq[0]);
-            m_crlValue = Asn1TaggedObject.GetInstance(seq[1]).GetObject();
+            m_crlValue = Asn1TaggedObject.GetInstance(seq[1]).GetExplicitBaseObject();
         }
 
         public CrlBag(DerObjectIdentifier crlID, Asn1Encodable crlValue)
diff --git a/crypto/src/asn1/pkcs/SafeBag.cs b/crypto/src/asn1/pkcs/SafeBag.cs
index 0c4f3972b..8b35a6717 100644
--- a/crypto/src/asn1/pkcs/SafeBag.cs
+++ b/crypto/src/asn1/pkcs/SafeBag.cs
@@ -42,7 +42,7 @@ namespace Org.BouncyCastle.Asn1.Pkcs
 		private SafeBag(Asn1Sequence seq)
         {
             this.bagID = (DerObjectIdentifier)seq[0];
-            this.bagValue = ((Asn1TaggedObject)seq[1]).GetObject();
+            this.bagValue = ((Asn1TaggedObject)seq[1]).GetExplicitBaseObject().ToAsn1Object();
             if (seq.Count == 3)
             {
                 this.bagAttributes = (Asn1Set)seq[2];
diff --git a/crypto/src/asn1/x500/DirectoryString.cs b/crypto/src/asn1/x500/DirectoryString.cs
index 6585fcdf5..154e4940e 100644
--- a/crypto/src/asn1/x500/DirectoryString.cs
+++ b/crypto/src/asn1/x500/DirectoryString.cs
@@ -29,15 +29,10 @@ namespace Org.BouncyCastle.Asn1.X500
             throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj");
 		}
 
-		public static DirectoryString GetInstance(
-			Asn1TaggedObject	obj,
-			bool				isExplicit)
-		{
-			if (!isExplicit)
-				throw new ArgumentException("choice item must be explicitly tagged");
-
-			return GetInstance(obj.GetObject());
-		}
+        public static DirectoryString GetInstance(Asn1TaggedObject obj, bool isExplicit)
+        {
+            return Asn1Utilities.GetInstanceFromChoice(obj, isExplicit, GetInstance);
+        }
 
 		private DirectoryString(
 			DerStringBase str)
diff --git a/crypto/src/asn1/x509/AttCertIssuer.cs b/crypto/src/asn1/x509/AttCertIssuer.cs
index 9d74f631e..39ff28790 100644
--- a/crypto/src/asn1/x509/AttCertIssuer.cs
+++ b/crypto/src/asn1/x509/AttCertIssuer.cs
@@ -36,11 +36,9 @@ namespace Org.BouncyCastle.Asn1.X509
             throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj");
         }
 
-        public static AttCertIssuer GetInstance(
-			Asn1TaggedObject	obj,
-			bool				isExplicit)
+        public static AttCertIssuer GetInstance(Asn1TaggedObject obj, bool isExplicit)
 		{
-			return GetInstance(obj.GetObject()); // must be explictly tagged
+            return Asn1Utilities.GetInstanceFromChoice(obj, isExplicit, GetInstance);
 		}
 
 		/// <summary>
diff --git a/crypto/src/asn1/x509/DisplayText.cs b/crypto/src/asn1/x509/DisplayText.cs
index 39b3c98d7..772e3f522 100644
--- a/crypto/src/asn1/x509/DisplayText.cs
+++ b/crypto/src/asn1/x509/DisplayText.cs
@@ -140,23 +140,23 @@ namespace Org.BouncyCastle.Asn1.X509
 			this.contents = contents;
 		}
 
-		public static DisplayText GetInstance(
-			object obj)
+		public static DisplayText GetInstance(object obj)
 		{
-			if (obj is IAsn1String)
-			{
-				return new DisplayText((IAsn1String) obj);
-			}
+			if (obj is IAsn1String asn1String)
+				return new DisplayText(asn1String);
 
-			if (obj is DisplayText)
-			{
-				return (DisplayText) obj;
-			}
+			if (obj is DisplayText displayText)
+				return displayText;
 
             throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj");
 		}
 
-		public override Asn1Object ToAsn1Object()
+		public static DisplayText GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+		{
+            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
+        }
+
+        public override Asn1Object ToAsn1Object()
 		{
 			return (Asn1Object) contents;
 		}
diff --git a/crypto/src/asn1/x509/Time.cs b/crypto/src/asn1/x509/Time.cs
index f7746257c..99d141c43 100644
--- a/crypto/src/asn1/x509/Time.cs
+++ b/crypto/src/asn1/x509/Time.cs
@@ -24,7 +24,7 @@ namespace Org.BouncyCastle.Asn1.X509
 
         public static Time GetInstance(Asn1TaggedObject	taggedObject, bool declaredExplicit)
         {
-            return GetInstance(taggedObject.GetObject());
+            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
         }
 
         private readonly Asn1Object m_timeObject;
diff --git a/crypto/src/asn1/x509/X509Extensions.cs b/crypto/src/asn1/x509/X509Extensions.cs
index 390bf46b7..d4497d255 100644
--- a/crypto/src/asn1/x509/X509Extensions.cs
+++ b/crypto/src/asn1/x509/X509Extensions.cs
@@ -215,7 +215,11 @@ namespace Org.BouncyCastle.Asn1.X509
                 return new X509Extensions(sequence);
 
             if (obj is Asn1TaggedObject taggedObject)
-                return GetInstance(taggedObject.GetObject());
+            {
+                Asn1Utilities.CheckTagClass(taggedObject, Asn1Tags.ContextSpecific);
+
+                return GetInstance(taggedObject.GetBaseObject().ToAsn1Object());
+            }
 
             throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj");
         }
diff --git a/crypto/src/asn1/x9/OtherInfo.cs b/crypto/src/asn1/x9/OtherInfo.cs
index c1819a5ee..19bf3f401 100644
--- a/crypto/src/asn1/x9/OtherInfo.cs
+++ b/crypto/src/asn1/x9/OtherInfo.cs
@@ -32,13 +32,13 @@ namespace Org.BouncyCastle.Asn1.X9
             {
                 Asn1TaggedObject o = (Asn1TaggedObject)e.Current;
 
-				if (o.TagNo == 0)
+				if (o.HasContextTag(0))
                 {
-                    partyAInfo = (Asn1OctetString)o.GetObject();
+                    partyAInfo = (Asn1OctetString)o.GetExplicitBaseObject();
                 }
-                else if ((int) o.TagNo == 2)
+                else if (o.HasContextTag(2))
                 {
-                    suppPubInfo = (Asn1OctetString)o.GetObject();
+                    suppPubInfo = (Asn1OctetString)o.GetExplicitBaseObject();
                 }
             }
         }
diff --git a/crypto/src/asn1/x9/X962Parameters.cs b/crypto/src/asn1/x9/X962Parameters.cs
index b863f4bfd..af1fce1db 100644
--- a/crypto/src/asn1/x9/X962Parameters.cs
+++ b/crypto/src/asn1/x9/X962Parameters.cs
@@ -9,24 +9,22 @@ namespace Org.BouncyCastle.Asn1.X9
     {
         private readonly Asn1Object _params;
 
-		public static X962Parameters GetInstance(
-			object obj)
+		public static X962Parameters GetInstance(object obj)
 		{
-			if (obj == null || obj is X962Parameters) 
-			{
-				return (X962Parameters)obj;
-			}
+            if (obj == null)
+                return null;
 
-			if (obj is Asn1Object) 
-			{
-				return new X962Parameters((Asn1Object)obj);
-			}
+			if (obj is X962Parameters x962Parameters)
+				return x962Parameters;
 
-			if (obj is byte[])
+			if (obj is Asn1Object asn1Object)
+				return new X962Parameters(asn1Object);
+
+			if (obj is byte[] bytes)
 			{
 				try
 				{
-					return new X962Parameters(Asn1Object.FromByteArray((byte[])obj));
+					return new X962Parameters(Asn1Object.FromByteArray(bytes));
 				}
 				catch (Exception e)
 				{
@@ -34,9 +32,14 @@ namespace Org.BouncyCastle.Asn1.X9
 				}
 			}
 
-			throw new ArgumentException("unknown object in getInstance()");
+			throw new ArgumentException("unknown object in GetInstance()");
 		}
 
+        public static X962Parameters GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
+        }
+
 		public X962Parameters(
             X9ECParameters ecParameters)
         {