summary refs log tree commit diff
path: root/crypto/src/asn1/pkcs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/asn1/pkcs')
-rw-r--r--crypto/src/asn1/pkcs/Attribute.cs73
-rw-r--r--crypto/src/asn1/pkcs/AuthenticatedSafe.cs57
-rw-r--r--crypto/src/asn1/pkcs/CertBag.cs29
-rw-r--r--crypto/src/asn1/pkcs/CertificationRequest.cs55
-rw-r--r--crypto/src/asn1/pkcs/CertificationRequestInfo.cs118
-rw-r--r--crypto/src/asn1/pkcs/ContentInfo.cs56
-rw-r--r--crypto/src/asn1/pkcs/CrlBag.cs25
-rw-r--r--crypto/src/asn1/pkcs/DHParameter.cs76
-rw-r--r--crypto/src/asn1/pkcs/EncryptedData.cs81
-rw-r--r--crypto/src/asn1/pkcs/EncryptedPrivateKeyInfo.cs55
-rw-r--r--crypto/src/asn1/pkcs/EncryptionScheme.cs1
-rw-r--r--crypto/src/asn1/pkcs/IssuerAndSerialNumber.cs72
-rw-r--r--crypto/src/asn1/pkcs/KeyDerivationFunc.cs4
-rw-r--r--crypto/src/asn1/pkcs/MacData.cs90
-rw-r--r--crypto/src/asn1/pkcs/PBEParameter.cs43
-rw-r--r--crypto/src/asn1/pkcs/PBES2Parameters.cs60
-rw-r--r--crypto/src/asn1/pkcs/PBKDF2Params.cs146
-rw-r--r--crypto/src/asn1/pkcs/PKCS12PBEParams.cs66
-rw-r--r--crypto/src/asn1/pkcs/Pfx.cs47
-rw-r--r--crypto/src/asn1/pkcs/PrivateKeyInfo.cs181
-rw-r--r--crypto/src/asn1/pkcs/RC2CBCParameter.cs79
-rw-r--r--crypto/src/asn1/pkcs/RSAESOAEPparams.cs161
-rw-r--r--crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs130
-rw-r--r--crypto/src/asn1/pkcs/RSASSAPSSparams.cs167
-rw-r--r--crypto/src/asn1/pkcs/SafeBag.cs75
-rw-r--r--crypto/src/asn1/pkcs/SignedData.cs140
-rw-r--r--crypto/src/asn1/pkcs/SignerInfo.cs136
27 files changed, 924 insertions, 1299 deletions
diff --git a/crypto/src/asn1/pkcs/Attribute.cs b/crypto/src/asn1/pkcs/Attribute.cs
index 185828596..3bd4aa4e5 100644
--- a/crypto/src/asn1/pkcs/Attribute.cs
+++ b/crypto/src/asn1/pkcs/Attribute.cs
@@ -1,66 +1,46 @@
 using System;
 
-using Org.BouncyCastle.Utilities;
-
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
     public class AttributePkcs
         : Asn1Encodable
     {
-        private readonly DerObjectIdentifier attrType;
-        private readonly Asn1Set attrValues;
-
-		/**
-         * return an Attribute object from the given object.
-         *
-         * @param o the object we want converted.
-         * @exception ArgumentException if the object cannot be converted.
-         */
-        public static AttributePkcs GetInstance(
-            object obj)
+        public static AttributePkcs GetInstance(object obj)
         {
-            AttributePkcs attr = obj as AttributePkcs;
-            if (obj == null || attr != null)
-            {
-                return attr;
-            }
+            if (obj == null)
+                return null;
+            if (obj is AttributePkcs attributePkcs)
+                return attributePkcs;
+            return new AttributePkcs(Asn1Sequence.GetInstance(obj));
+		}
 
-			Asn1Sequence seq = obj as Asn1Sequence;
-            if (seq != null)
-            {
-                return new AttributePkcs(seq);
-            }
+        public static AttributePkcs GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return new AttributePkcs(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
 
-			throw new ArgumentException("Unknown object in factory: " + Platform.GetTypeName(obj), "obj");
-		}
+        private readonly DerObjectIdentifier m_attrType;
+        private readonly Asn1Set m_attrValues;
 
-		private AttributePkcs(
-            Asn1Sequence seq)
+        private AttributePkcs(Asn1Sequence seq)
         {
-			if (seq.Count != 2)
-				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+            int count = seq.Count;
+            if (count != 2)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-			attrType = DerObjectIdentifier.GetInstance(seq[0]);
-            attrValues = Asn1Set.GetInstance(seq[1]);
+			m_attrType = DerObjectIdentifier.GetInstance(seq[0]);
+            m_attrValues = Asn1Set.GetInstance(seq[1]);
         }
 
-		public AttributePkcs(
-            DerObjectIdentifier	attrType,
-            Asn1Set				attrValues)
+		public AttributePkcs(DerObjectIdentifier attrType, Asn1Set attrValues)
         {
-            this.attrType = attrType;
-            this.attrValues = attrValues;
+            m_attrType = attrType ?? throw new ArgumentNullException(nameof(attrType));
+            m_attrValues = attrValues ?? throw new ArgumentNullException(nameof(attrValues));
         }
 
-		public DerObjectIdentifier AttrType
-		{
-			get { return attrType; }
-		}
+        public DerObjectIdentifier AttrType => m_attrType;
 
-		public Asn1Set AttrValues
-		{
-			get { return attrValues; }
-		}
+        public Asn1Set AttrValues => m_attrValues;
 
 		/**
          * Produce an object suitable for an Asn1OutputStream.
@@ -71,9 +51,6 @@ namespace Org.BouncyCastle.Asn1.Pkcs
          * }
          * </pre>
          */
-        public override Asn1Object ToAsn1Object()
-        {
-			return new DerSequence(attrType, attrValues);
-        }
+        public override Asn1Object ToAsn1Object() => new DerSequence(m_attrType, m_attrValues);
     }
 }
diff --git a/crypto/src/asn1/pkcs/AuthenticatedSafe.cs b/crypto/src/asn1/pkcs/AuthenticatedSafe.cs
index 6f3b4c8c3..0d8379179 100644
--- a/crypto/src/asn1/pkcs/AuthenticatedSafe.cs
+++ b/crypto/src/asn1/pkcs/AuthenticatedSafe.cs
@@ -1,63 +1,46 @@
-using System;
-
-using Org.BouncyCastle.Asn1;
-
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
     public class AuthenticatedSafe
         : Asn1Encodable
     {
-        private static ContentInfo[] Copy(ContentInfo[] info)
-        {
-            return (ContentInfo[])info.Clone();
-        }
-
         public static AuthenticatedSafe GetInstance(object obj)
         {
-            if (obj is AuthenticatedSafe)
-                return (AuthenticatedSafe)obj;
             if (obj == null)
                 return null;
+            if (obj is AuthenticatedSafe authenticatedSafe)
+                return authenticatedSafe;
             return new AuthenticatedSafe(Asn1Sequence.GetInstance(obj));
         }
 
-        private readonly ContentInfo[] info;
-        private readonly bool isBer;
-
-		private AuthenticatedSafe(Asn1Sequence seq)
+        public static AuthenticatedSafe GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
         {
-            info = new ContentInfo[seq.Count];
-
-            for (int i = 0; i != info.Length; i++)
-            {
-                info[i] = ContentInfo.GetInstance(seq[i]);
-            }
-
-            isBer = seq is BerSequence;
+            return new AuthenticatedSafe(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
-		public AuthenticatedSafe(
-            ContentInfo[] info)
+        private readonly ContentInfo[] m_info;
+        private readonly bool m_isBer;
+
+		private AuthenticatedSafe(Asn1Sequence seq)
         {
-            this.info = Copy(info);
-            this.isBer = true;
+            m_info = seq.MapElements(ContentInfo.GetInstance);
+            m_isBer = seq is BerSequence;
         }
 
-		public ContentInfo[] GetContentInfo()
+		public AuthenticatedSafe(ContentInfo[] info)
         {
-            return Copy(info);
+            m_info = Copy(info);
+            m_isBer = true;
         }
 
+        public ContentInfo[] GetContentInfo() => Copy(m_info);
+
         public override Asn1Object ToAsn1Object()
         {
-            if (isBer)
-            {
-                return new BerSequence(info);
-            }
-
-            // TODO bc-java uses DL sequence
-            //return new DLSequence(info);
-            return new DerSequence(info);
+            return m_isBer
+                ?  new BerSequence(m_info)
+                :  new DLSequence(m_info);
         }
+
+        private static ContentInfo[] Copy(ContentInfo[] info) => (ContentInfo[])info.Clone();
     }
 }
diff --git a/crypto/src/asn1/pkcs/CertBag.cs b/crypto/src/asn1/pkcs/CertBag.cs
index 129a73ada..bce67cd0a 100644
--- a/crypto/src/asn1/pkcs/CertBag.cs
+++ b/crypto/src/asn1/pkcs/CertBag.cs
@@ -7,38 +7,43 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     {
         public static CertBag GetInstance(object obj)
         {
-            if (obj is CertBag certBag)
-                return certBag;
             if (obj == null)
                 return null;
+            if (obj is CertBag certBag)
+                return certBag;
             return new CertBag(Asn1Sequence.GetInstance(obj));
         }
 
+        public static CertBag GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return new CertBag(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
         private readonly DerObjectIdentifier m_certID;
         private readonly Asn1Object m_certValue;
 
 		private CertBag(Asn1Sequence seq)
         {
-			if (seq.Count != 2)
-				throw new ArgumentException("Wrong number of elements in sequence", nameof(seq));
+            int count = seq.Count;
+            if (count != 2)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-            this.m_certID = DerObjectIdentifier.GetInstance(seq[0]);
-            this.m_certValue = Asn1TaggedObject.GetInstance(seq[1]).GetExplicitBaseObject().ToAsn1Object();
+            m_certID = DerObjectIdentifier.GetInstance(seq[0]);
+            m_certValue = Asn1TaggedObject.GetInstance(seq[1], Asn1Tags.ContextSpecific, 0)
+                .GetExplicitBaseObject().ToAsn1Object();
         }
 
 		public CertBag(DerObjectIdentifier certID, Asn1Object certValue)
         {
-            m_certID = certID;
-            m_certValue = certValue;
+            m_certID = certID ?? throw new ArgumentNullException(nameof(certID));
+            m_certValue = certValue ?? throw new ArgumentNullException(nameof(certValue));
         }
 
         public virtual DerObjectIdentifier CertID => m_certID;
 
+        // TODO[api] Prefer returning Asn1Encodable
         public virtual Asn1Object CertValue => m_certValue;
 
-		public override Asn1Object ToAsn1Object()
-        {
-			return new DerSequence(m_certID, new DerTaggedObject(0, m_certValue));
-        }
+		public override Asn1Object ToAsn1Object() => new DerSequence(m_certID, new DerTaggedObject(0, m_certValue));
     }
 }
diff --git a/crypto/src/asn1/pkcs/CertificationRequest.cs b/crypto/src/asn1/pkcs/CertificationRequest.cs
index 8c4248d36..9a7c28ab1 100644
--- a/crypto/src/asn1/pkcs/CertificationRequest.cs
+++ b/crypto/src/asn1/pkcs/CertificationRequest.cs
@@ -14,31 +14,34 @@ namespace Org.BouncyCastle.Asn1.Pkcs
      * }
      * </pre>
      */
+    // TODO[api] Stop subclassing this class
     public class CertificationRequest
         : Asn1Encodable
     {
-        protected CertificationRequestInfo	reqInfo;
-        protected AlgorithmIdentifier		sigAlgId;
-        protected DerBitString				sigBits;
-
-		public static CertificationRequest GetInstance(
-			object obj)
+		public static CertificationRequest GetInstance(object obj)
 		{
             if (obj == null)
                 return null;
-            if (obj is CertificationRequest)
-				return (CertificationRequest)obj;
+            if (obj is CertificationRequest certificationRequest)
+				return certificationRequest;
             return new CertificationRequest(Asn1Sequence.GetInstance(obj));
 		}
 
-		protected CertificationRequest()
+        public static CertificationRequest GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return new CertificationRequest(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
+        protected CertificationRequestInfo reqInfo;
+        protected AlgorithmIdentifier sigAlgId;
+        protected DerBitString sigBits;
+
+        protected CertificationRequest()
         {
         }
 
-		public CertificationRequest(
-            CertificationRequestInfo	requestInfo,
-            AlgorithmIdentifier			algorithm,
-            DerBitString				signature)
+        public CertificationRequest(CertificationRequestInfo requestInfo, AlgorithmIdentifier algorithm,
+            DerBitString signature)
         {
             this.reqInfo = requestInfo;
             this.sigAlgId = algorithm;
@@ -55,29 +58,15 @@ namespace Org.BouncyCastle.Asn1.Pkcs
             sigBits = DerBitString.GetInstance(seq[2]);
         }
 
-		public CertificationRequestInfo GetCertificationRequestInfo()
-        {
-            return reqInfo;
-        }
+        // TODO[api] Rename as a property
+        public CertificationRequestInfo GetCertificationRequestInfo() => reqInfo;
 
-		public AlgorithmIdentifier SignatureAlgorithm
-		{
-			get { return sigAlgId; }
-		}
+		public AlgorithmIdentifier SignatureAlgorithm => sigAlgId;
 
-		public DerBitString Signature
-		{
-			get { return sigBits; }
-		}
+		public DerBitString Signature => sigBits;
 
-        public byte[] GetSignatureOctets()
-        {
-            return sigBits.GetOctets();
-        }
+        public byte[] GetSignatureOctets() => sigBits.GetOctets();
 
-        public override Asn1Object ToAsn1Object()
-        {
-			return new DerSequence(reqInfo, sigAlgId, sigBits);
-        }
+        public override Asn1Object ToAsn1Object() => new DerSequence(reqInfo, sigAlgId, sigBits);
     }
 }
diff --git a/crypto/src/asn1/pkcs/CertificationRequestInfo.cs b/crypto/src/asn1/pkcs/CertificationRequestInfo.cs
index 196d9f4e5..53bdffdaa 100644
--- a/crypto/src/asn1/pkcs/CertificationRequestInfo.cs
+++ b/crypto/src/asn1/pkcs/CertificationRequestInfo.cs
@@ -25,107 +25,83 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     public class CertificationRequestInfo
         : Asn1Encodable
     {
-        internal DerInteger				version = DerInteger.Zero;
-        internal X509Name				subject;
-        internal SubjectPublicKeyInfo	subjectPKInfo;
-        internal Asn1Set				attributes;
-
 		public static CertificationRequestInfo GetInstance(object obj)
         {
-            if (obj is CertificationRequestInfo)
-                return (CertificationRequestInfo)obj;
-            if (obj != null)
-                return new CertificationRequestInfo(Asn1Sequence.GetInstance(obj));
-            return null;
+            if (obj == null)
+                return null;
+            if (obj is CertificationRequestInfo certificationRequestInfo)
+                return certificationRequestInfo;
+            return new CertificationRequestInfo(Asn1Sequence.GetInstance(obj));
 		}
 
-		public CertificationRequestInfo(
-            X509Name				subject,
-            SubjectPublicKeyInfo	pkInfo,
-            Asn1Set					attributes)
+        public static CertificationRequestInfo GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
         {
-            this.subject = subject;
-            this.subjectPKInfo = pkInfo;
-            this.attributes = attributes;
+            return new CertificationRequestInfo(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
 
-            ValidateAttributes(attributes);
+        private readonly DerInteger m_version;
+        private readonly X509Name m_subject;
+        private readonly SubjectPublicKeyInfo m_subjectPKInfo;
+        private readonly Asn1Set m_attributes;
 
-            if (subject == null || version == null || subjectPKInfo == null)
-            {
-                throw new ArgumentException(
-					"Not all mandatory fields set in CertificationRequestInfo generator.");
-            }
+        public CertificationRequestInfo(X509Name subject, SubjectPublicKeyInfo pkInfo, Asn1Set attributes)
+        {
+            m_version = DerInteger.Zero;
+            m_subject = subject ?? throw new ArgumentNullException(nameof(subject));
+            m_subjectPKInfo = pkInfo ?? throw new ArgumentNullException(nameof(pkInfo));
+            m_attributes = ValidateAttributes(attributes);
         }
 
-		private CertificationRequestInfo(
-            Asn1Sequence seq)
+		private CertificationRequestInfo(Asn1Sequence seq)
         {
-            version = (DerInteger) seq[0];
+            int count = seq.Count, pos = 0;
+            if (count < 3 || count > 4)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-			subject = X509Name.GetInstance(seq[1]);
-            subjectPKInfo = SubjectPublicKeyInfo.GetInstance(seq[2]);
+            m_version = DerInteger.GetInstance(seq[pos++]);
+            m_subject = X509Name.GetInstance(seq[pos++]);
+            m_subjectPKInfo = SubjectPublicKeyInfo.GetInstance(seq[pos++]);
 
-			//
-            // some CertificationRequestInfo objects seem to treat this field
-            // as optional.
-            //
-            if (seq.Count > 3)
-            {
-                Asn1TaggedObject tagobj = (Asn1TaggedObject)seq[3];
-                attributes = Asn1Set.GetInstance(tagobj, false);
-            }
+            // NOTE: some CertificationRequestInfo objects seem to treat this field as optional.
+            m_attributes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetInstance);
 
-            ValidateAttributes(attributes);
+            if (pos != count)
+                throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
 
-            if (subject == null || version == null || subjectPKInfo == null)
-            {
-                throw new ArgumentException(
-					"Not all mandatory fields set in CertificationRequestInfo generator.");
-            }
+            ValidateAttributes(m_attributes);
         }
 
-		public DerInteger Version
-		{
-			get { return version; }
-		}
+        public DerInteger Version => m_version;
 
-		public X509Name Subject
-		{
-			get { return subject; }
-		}
+        public X509Name Subject => m_subject;
 
-		public SubjectPublicKeyInfo SubjectPublicKeyInfo
-		{
-			get { return subjectPKInfo; }
-		}
+        public SubjectPublicKeyInfo SubjectPublicKeyInfo => m_subjectPKInfo;
 
-		public Asn1Set Attributes
-		{
-			get { return attributes; }
-		}
+        public Asn1Set Attributes => m_attributes;
 
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(version, subject, subjectPKInfo);
-            v.AddOptionalTagged(false, 0, attributes);
+            Asn1EncodableVector v = new Asn1EncodableVector(4);
+            v.Add(m_version, m_subject, m_subjectPKInfo);
+            v.AddOptionalTagged(false, 0, m_attributes);
             return new DerSequence(v);
         }
 
-        private static void ValidateAttributes(Asn1Set attributes)
+        private static Asn1Set ValidateAttributes(Asn1Set attributes)
         {
-            if (attributes == null)
-                return;
-
-            foreach (Asn1Encodable ae in attributes)
+            if (attributes != null)
             {
-                Asn1Object obj = ae.ToAsn1Object();
-                AttributePkcs attr = AttributePkcs.GetInstance(obj);
-                if (attr.AttrType.Equals(PkcsObjectIdentifiers.Pkcs9AtChallengePassword))
+                foreach (var element in attributes)
                 {
-                    if (attr.AttrValues.Count != 1)
-                        throw new ArgumentException("challengePassword attribute must have one value");
+                    AttributePkcs attr = AttributePkcs.GetInstance(element);
+                    if (PkcsObjectIdentifiers.Pkcs9AtChallengePassword.Equals(attr.AttrType))
+                    {
+                        if (attr.AttrValues.Count != 1)
+                            throw new ArgumentException("challengePassword attribute must have one value");
+                    }
                 }
             }
+            return attributes;
         }
     }
 }
diff --git a/crypto/src/asn1/pkcs/ContentInfo.cs b/crypto/src/asn1/pkcs/ContentInfo.cs
index 0a19306f2..faf2360cc 100644
--- a/crypto/src/asn1/pkcs/ContentInfo.cs
+++ b/crypto/src/asn1/pkcs/ContentInfo.cs
@@ -1,11 +1,10 @@
+using System;
+
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
     public class ContentInfo
         : Asn1Encodable
     {
-        private readonly DerObjectIdentifier	contentType;
-        private readonly Asn1Encodable			content;
-
         public static ContentInfo GetInstance(object obj)
         {
             if (obj == null)
@@ -15,54 +14,51 @@ namespace Org.BouncyCastle.Asn1.Pkcs
             return new ContentInfo(Asn1Sequence.GetInstance(obj));
         }
 
-        private ContentInfo(
-            Asn1Sequence seq)
+        public static ContentInfo GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return new ContentInfo(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
+        private readonly DerObjectIdentifier m_contentType;
+        private readonly Asn1Encodable m_content;
+
+        private ContentInfo(Asn1Sequence seq)
         {
-            contentType = (DerObjectIdentifier) seq[0];
+            int count = seq.Count;
+            if (count < 1 || count > 2)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
+
+            m_contentType = DerObjectIdentifier.GetInstance(seq[0]);
 
             if (seq.Count > 1)
             {
-                content = ((Asn1TaggedObject) seq[1]).GetExplicitBaseObject();
+                m_content = Asn1TaggedObject.GetInstance(seq[1], Asn1Tags.ContextSpecific, 0).GetExplicitBaseObject();
             }
         }
 
-        public ContentInfo(
-            DerObjectIdentifier	contentType,
-            Asn1Encodable		content)
+        public ContentInfo(DerObjectIdentifier contentType, Asn1Encodable content)
         {
-            this.contentType = contentType;
-            this.content = content;
+            m_contentType = contentType ?? throw new ArgumentNullException(nameof(contentType));
+            m_content = content;
         }
 
-        public DerObjectIdentifier ContentType
-        {
-            get { return contentType; }
-        }
+        public DerObjectIdentifier ContentType => m_contentType;
 
-        public Asn1Encodable Content
-        {
-            get { return content; }
-        }
+        public Asn1Encodable Content => m_content;
 
         /**
          * Produce an object suitable for an Asn1OutputStream.
          * <pre>
          * ContentInfo ::= Sequence {
          *          contentType ContentType,
-         *          content
-         *          [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+         *          content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
          * </pre>
          */
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(contentType);
-
-            if (content != null)
-            {
-                v.Add(new BerTaggedObject(0, content));
-            }
-
-            return new BerSequence(v);
+            return m_content == null
+                ?  new BerSequence(m_contentType)
+                :  new BerSequence(m_contentType, new BerTaggedObject(0, m_content));
         }
     }
 }
diff --git a/crypto/src/asn1/pkcs/CrlBag.cs b/crypto/src/asn1/pkcs/CrlBag.cs
index 0198c341c..28cc19fb1 100644
--- a/crypto/src/asn1/pkcs/CrlBag.cs
+++ b/crypto/src/asn1/pkcs/CrlBag.cs
@@ -7,38 +7,41 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     {
         public static CrlBag GetInstance(object obj)
         {
-            if (obj is CrlBag crlBag)
-                return crlBag;
             if (obj == null)
                 return null;
+            if (obj is CrlBag crlBag)
+                return crlBag;
             return new CrlBag(Asn1Sequence.GetInstance(obj));
         }
 
+        public static CrlBag GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return new CrlBag(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
         private readonly DerObjectIdentifier m_crlID;
         private readonly Asn1Encodable m_crlValue;
 
         private CrlBag(Asn1Sequence seq)
         {
-            if (seq.Count != 2)
-                throw new ArgumentException("Wrong number of elements in sequence", nameof(seq));
+            int count = seq.Count;
+            if (count != 2)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
             m_crlID = DerObjectIdentifier.GetInstance(seq[0]);
-            m_crlValue = Asn1TaggedObject.GetInstance(seq[1]).GetExplicitBaseObject();
+            m_crlValue = Asn1TaggedObject.GetInstance(seq[1], Asn1Tags.ContextSpecific, 0).GetExplicitBaseObject();
         }
 
         public CrlBag(DerObjectIdentifier crlID, Asn1Encodable crlValue)
         {
-            m_crlID = crlID;
-            m_crlValue = crlValue;
+            m_crlID = crlID ?? throw new ArgumentNullException(nameof(crlID));
+            m_crlValue = crlValue ?? throw new ArgumentNullException(nameof(crlValue));
         }
 
         public virtual DerObjectIdentifier CrlID => m_crlID;
 
         public virtual Asn1Encodable CrlValue => m_crlValue;
 
-        public override Asn1Object ToAsn1Object()
-        {
-            return new DerSequence(m_crlID, new DerTaggedObject(0, m_crlValue));
-        }
+        public override Asn1Object ToAsn1Object() => new DerSequence(m_crlID, new DerTaggedObject(0, m_crlValue));
     }
 }
diff --git a/crypto/src/asn1/pkcs/DHParameter.cs b/crypto/src/asn1/pkcs/DHParameter.cs
index 7a07a18b0..43a6129d4 100644
--- a/crypto/src/asn1/pkcs/DHParameter.cs
+++ b/crypto/src/asn1/pkcs/DHParameter.cs
@@ -1,3 +1,5 @@
+using System;
+
 using Org.BouncyCastle.Math;
 
 namespace Org.BouncyCastle.Asn1.Pkcs
@@ -5,59 +7,63 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     public class DHParameter
         : Asn1Encodable
     {
-        internal DerInteger p, g, l;
+        public static DHParameter GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is DHParameter dhParameter)
+                return dhParameter;
+#pragma warning disable CS0618 // Type or member is obsolete
+            return new DHParameter(Asn1Sequence.GetInstance(obj));
+#pragma warning restore CS0618 // Type or member is obsolete
+        }
 
-		public DHParameter(
-            BigInteger	p,
-            BigInteger	g,
-            int			l)
+        public static DHParameter GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
         {
-            this.p = new DerInteger(p);
-            this.g = new DerInteger(g);
+#pragma warning disable CS0618 // Type or member is obsolete
+            return new DHParameter(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+#pragma warning restore CS0618 // Type or member is obsolete
+        }
+
+        private readonly DerInteger m_p, m_g, m_l;
+
+        public DHParameter(BigInteger p, BigInteger g, int l)
+        {
+            m_p = new DerInteger(p);
+            m_g = new DerInteger(g);
 
 			if (l != 0)
             {
-                this.l = new DerInteger(l);
+                m_l = new DerInteger(l);
             }
         }
 
-		public DHParameter(
-            Asn1Sequence seq)
+        [Obsolete("Use 'GetInstance' instead")]
+        public DHParameter(Asn1Sequence seq)
         {
-            var e = seq.GetEnumerator();
-
-			e.MoveNext();
-            p = (DerInteger)e.Current;
+            int count = seq.Count, pos = 0;
+            if (count < 2 || count > 3)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-			e.MoveNext();
-            g = (DerInteger)e.Current;
+            m_p = DerInteger.GetInstance(seq[pos++]);
+            m_g = DerInteger.GetInstance(seq[pos++]);
+            m_l = Asn1Utilities.ReadOptional(seq, ref pos, DerInteger.GetOptional);
 
-			if (e.MoveNext())
-            {
-                l = (DerInteger) e.Current;
-            }
+            if (pos != count)
+                throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
         }
 
-		public BigInteger P
-		{
-			get { return p.PositiveValue; }
-		}
+        public BigInteger P => m_p.PositiveValue;
 
-		public BigInteger G
-		{
-			get { return g.PositiveValue; }
-		}
+        public BigInteger G => m_g.PositiveValue;
 
-		public BigInteger L
-		{
-            get { return l == null ? null : l.PositiveValue; }
-        }
+        public BigInteger L => m_l?.PositiveValue;
 
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(p, g);
-            v.AddOptional(l);
-            return new DerSequence(v);
+            return m_l == null
+                ?  new DerSequence(m_p, m_g)
+                :  new DerSequence(m_p, m_g, m_l);
         }
     }
 }
diff --git a/crypto/src/asn1/pkcs/EncryptedData.cs b/crypto/src/asn1/pkcs/EncryptedData.cs
index f75975d5a..0b971eeeb 100644
--- a/crypto/src/asn1/pkcs/EncryptedData.cs
+++ b/crypto/src/asn1/pkcs/EncryptedData.cs
@@ -1,7 +1,6 @@
 using System;
 
 using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
@@ -26,78 +25,60 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     public class EncryptedData
         : Asn1Encodable
     {
-        private readonly Asn1Sequence data;
-//        private readonly DerObjectIdentifier bagId;
-//        private readonly Asn1Object bagValue;
+        private readonly Asn1Sequence m_data;
+        //        private readonly DerObjectIdentifier bagId;
+        //        private readonly Asn1Object bagValue;
 
-		public static EncryptedData GetInstance(
-             object obj)
+        public static EncryptedData GetInstance(object obj)
         {
-			if (obj is EncryptedData)
-			{
-				return (EncryptedData) obj;
-			}
-
-			if (obj is Asn1Sequence)
-			{
-				return new EncryptedData((Asn1Sequence) obj);
-			}
+            if (obj == null)
+                return null;
+            if (obj is EncryptedData encryptedData)
+                return encryptedData;
+            return new EncryptedData(Asn1Sequence.GetInstance(obj));
+        }
 
-			throw new ArgumentException("Unknown object in factory: " + Platform.GetTypeName(obj), "obj");
-		}
+        public static EncryptedData GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return new EncryptedData(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
 
-		private EncryptedData(
-            Asn1Sequence seq)
+        private EncryptedData(Asn1Sequence seq)
         {
-			if (seq.Count != 2)
-				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+            int count = seq.Count;
+            if (count != 2)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-            DerInteger version = (DerInteger)seq[0];
-			if (!version.HasValue(0))
+            DerInteger version = DerInteger.GetInstance(seq[0]);
+            if (!version.HasValue(0))
                 throw new ArgumentException("sequence not version 0");
 
-			this.data = (Asn1Sequence) seq[1];
+            m_data = Asn1Sequence.GetInstance(seq[1]);
         }
 
-		public EncryptedData(
-            DerObjectIdentifier	contentType,
-            AlgorithmIdentifier	encryptionAlgorithm,
-            Asn1Encodable		content)
+        public EncryptedData(DerObjectIdentifier contentType, AlgorithmIdentifier encryptionAlgorithm,
+            Asn1Encodable content)
         {
-			data = new BerSequence(
-				contentType,
-				encryptionAlgorithm.ToAsn1Object(),
-				new BerTaggedObject(false, 0, content));
+            m_data = new BerSequence(contentType, encryptionAlgorithm, new BerTaggedObject(false, 0, content));
         }
 
-		public DerObjectIdentifier ContentType
-        {
-            get { return (DerObjectIdentifier) data[0]; }
-        }
+        public DerObjectIdentifier ContentType => DerObjectIdentifier.GetInstance(m_data[0]);
 
-		public AlgorithmIdentifier EncryptionAlgorithm
-        {
-			get { return AlgorithmIdentifier.GetInstance(data[1]); }
-        }
+		public AlgorithmIdentifier EncryptionAlgorithm => AlgorithmIdentifier.GetInstance(m_data[1]);
 
 		public Asn1OctetString Content
         {
 			get
 			{
-				if (data.Count == 3)
-				{
-                    Asn1TaggedObject o = (Asn1TaggedObject)data[2];
+                if (m_data.Count != 3)
+                    return null;
 
-					return Asn1OctetString.GetInstance(o, false);
-				}
+                Asn1TaggedObject tagged = Asn1TaggedObject.GetInstance(m_data[2], Asn1Tags.ContextSpecific, 0);
 
-				return null;
+				return Asn1OctetString.GetInstance(tagged, declaredExplicit: false);
 			}
         }
 
-		public override Asn1Object ToAsn1Object()
-        {
-			return new BerSequence(DerInteger.Zero, data);
-        }
+		public override Asn1Object ToAsn1Object() => new BerSequence(DerInteger.Zero, m_data);
     }
 }
diff --git a/crypto/src/asn1/pkcs/EncryptedPrivateKeyInfo.cs b/crypto/src/asn1/pkcs/EncryptedPrivateKeyInfo.cs
index bf0e1aaeb..39f3e9c3e 100644
--- a/crypto/src/asn1/pkcs/EncryptedPrivateKeyInfo.cs
+++ b/crypto/src/asn1/pkcs/EncryptedPrivateKeyInfo.cs
@@ -7,26 +7,6 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     public class EncryptedPrivateKeyInfo
         : Asn1Encodable
     {
-        private readonly AlgorithmIdentifier algId;
-        private readonly Asn1OctetString data;
-
-		private EncryptedPrivateKeyInfo(Asn1Sequence seq)
-        {
-			if (seq.Count != 2)
-				throw new ArgumentException("Wrong number of elements in sequence", "seq");
-
-            algId = AlgorithmIdentifier.GetInstance(seq[0]);
-            data = Asn1OctetString.GetInstance(seq[1]);
-        }
-
-		public EncryptedPrivateKeyInfo(
-            AlgorithmIdentifier	algId,
-            byte[]				encoding)
-        {
-            this.algId = algId;
-            this.data = new DerOctetString(encoding);
-        }
-
         public static EncryptedPrivateKeyInfo GetInstance(object obj)
         {
             if (obj == null)
@@ -36,16 +16,34 @@ namespace Org.BouncyCastle.Asn1.Pkcs
             return new EncryptedPrivateKeyInfo(Asn1Sequence.GetInstance(obj));
         }
 
-		public AlgorithmIdentifier EncryptionAlgorithm
-		{
-			get { return algId; }
-		}
+        public static EncryptedPrivateKeyInfo GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return new EncryptedPrivateKeyInfo(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
 
-		public byte[] GetEncryptedData()
+        private readonly AlgorithmIdentifier m_encryptionAlgorithm;
+        private readonly Asn1OctetString m_encryptedData;
+
+		private EncryptedPrivateKeyInfo(Asn1Sequence seq)
+        {
+            int count = seq.Count;
+            if (count != 2)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
+
+            m_encryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]);
+            m_encryptedData = Asn1OctetString.GetInstance(seq[1]);
+        }
+
+        public EncryptedPrivateKeyInfo(AlgorithmIdentifier algId, byte[] encoding)
         {
-            return data.GetOctets();
+            m_encryptionAlgorithm = algId ?? throw new ArgumentNullException(nameof(algId));
+            m_encryptedData = new DerOctetString(encoding);
         }
 
+        public AlgorithmIdentifier EncryptionAlgorithm => m_encryptionAlgorithm;
+
+        public byte[] GetEncryptedData() => m_encryptedData.GetOctets();
+
 		/**
          * Produce an object suitable for an Asn1OutputStream.
          * <pre>
@@ -61,9 +59,6 @@ namespace Org.BouncyCastle.Asn1.Pkcs
          * }
          * </pre>
          */
-        public override Asn1Object ToAsn1Object()
-        {
-			return new DerSequence(algId, data);
-        }
+        public override Asn1Object ToAsn1Object() => new DerSequence(m_encryptionAlgorithm, m_encryptedData);
     }
 }
diff --git a/crypto/src/asn1/pkcs/EncryptionScheme.cs b/crypto/src/asn1/pkcs/EncryptionScheme.cs
index a073f8c17..9834e1523 100644
--- a/crypto/src/asn1/pkcs/EncryptionScheme.cs
+++ b/crypto/src/asn1/pkcs/EncryptionScheme.cs
@@ -2,6 +2,7 @@ using Org.BouncyCastle.Asn1.X509;
 
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
+    // TODO[api] This is not supposed to be a separate type; remove and use AlgorithmIdentifier
     public class EncryptionScheme
         : AlgorithmIdentifier
     {
diff --git a/crypto/src/asn1/pkcs/IssuerAndSerialNumber.cs b/crypto/src/asn1/pkcs/IssuerAndSerialNumber.cs
index da863cb62..0a2c05d41 100644
--- a/crypto/src/asn1/pkcs/IssuerAndSerialNumber.cs
+++ b/crypto/src/asn1/pkcs/IssuerAndSerialNumber.cs
@@ -2,71 +2,55 @@ using System;
 
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Math;
-using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
     public class IssuerAndSerialNumber
         : Asn1Encodable
     {
-        private readonly X509Name name;
-        private readonly DerInteger certSerialNumber;
-
-		public static IssuerAndSerialNumber GetInstance(
-            object obj)
+		public static IssuerAndSerialNumber GetInstance(object obj)
         {
-            if (obj is IssuerAndSerialNumber)
-            {
-                return (IssuerAndSerialNumber) obj;
-            }
+            if (obj == null)
+                return null;
+            if (obj is IssuerAndSerialNumber issuerAndSerialNumber)
+                return issuerAndSerialNumber;
+            return new IssuerAndSerialNumber(Asn1Sequence.GetInstance(obj));
+		}
 
-			if (obj is Asn1Sequence)
-            {
-                return new IssuerAndSerialNumber((Asn1Sequence) obj);
-            }
+        public static IssuerAndSerialNumber GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return new IssuerAndSerialNumber(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
 
-			throw new ArgumentException("Unknown object in factory: " + Platform.GetTypeName(obj), "obj");
-		}
+        private readonly X509Name m_name;
+        private readonly DerInteger m_certSerialNumber;
 
-		private IssuerAndSerialNumber(
-            Asn1Sequence seq)
+        private IssuerAndSerialNumber(Asn1Sequence seq)
         {
-			if (seq.Count != 2)
-				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+            int count = seq.Count;
+			if (count != 2)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-			this.name = X509Name.GetInstance(seq[0]);
-            this.certSerialNumber = DerInteger.GetInstance(seq[1]);
+            m_name = X509Name.GetInstance(seq[0]);
+            m_certSerialNumber = DerInteger.GetInstance(seq[1]);
         }
 
-		public IssuerAndSerialNumber(
-            X509Name	name,
-            BigInteger	certSerialNumber)
+        public IssuerAndSerialNumber(X509Name name, BigInteger certSerialNumber)
         {
-            this.name = name;
-            this.certSerialNumber = new DerInteger(certSerialNumber);
+            m_name = name ?? throw new ArgumentNullException(nameof(name));
+            m_certSerialNumber = new DerInteger(certSerialNumber);
         }
 
-		public IssuerAndSerialNumber(
-            X509Name	name,
-            DerInteger	certSerialNumber)
+        public IssuerAndSerialNumber(X509Name name, DerInteger certSerialNumber)
         {
-            this.name = name;
-            this.certSerialNumber = certSerialNumber;
+            m_name = name ?? throw new ArgumentNullException(nameof(name));
+            m_certSerialNumber = certSerialNumber ?? throw new ArgumentNullException(nameof(certSerialNumber));
         }
 
-		public X509Name Name
-		{
-			get { return name; }
-		}
+        public X509Name Name => m_name;
 
-		public DerInteger CertificateSerialNumber
-		{
-			get { return certSerialNumber; }
-		}
+        public DerInteger CertificateSerialNumber => m_certSerialNumber;
 
-		public override Asn1Object ToAsn1Object()
-        {
-			return new DerSequence(name, certSerialNumber);
-        }
+		public override Asn1Object ToAsn1Object() => new DerSequence(m_name, m_certSerialNumber);
     }
 }
diff --git a/crypto/src/asn1/pkcs/KeyDerivationFunc.cs b/crypto/src/asn1/pkcs/KeyDerivationFunc.cs
index 9fc89853b..64672df54 100644
--- a/crypto/src/asn1/pkcs/KeyDerivationFunc.cs
+++ b/crypto/src/asn1/pkcs/KeyDerivationFunc.cs
@@ -1,9 +1,9 @@
-using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.X509;
 
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
-	public class KeyDerivationFunc
+    // TODO[api] This is not supposed to be a separate type; remove and use AlgorithmIdentifier
+    public class KeyDerivationFunc
 		: AlgorithmIdentifier
 	{
 		internal KeyDerivationFunc(Asn1Sequence seq)
diff --git a/crypto/src/asn1/pkcs/MacData.cs b/crypto/src/asn1/pkcs/MacData.cs
index c4b7df176..d122dc45e 100644
--- a/crypto/src/asn1/pkcs/MacData.cs
+++ b/crypto/src/asn1/pkcs/MacData.cs
@@ -2,73 +2,56 @@ using System;
 
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Math;
-using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
     public class MacData
         : Asn1Encodable
     {
-        internal DigestInfo	digInfo;
-        internal byte[]		salt;
-        internal BigInteger	iterationCount;
-
-		public static MacData GetInstance(
-            object obj)
+        public static MacData GetInstance(object obj)
         {
-            if (obj is MacData)
-            {
-                return (MacData) obj;
-            }
+            if (obj == null)
+                return null;
+            if (obj is MacData macData)
+                return macData;
+            return new MacData(Asn1Sequence.GetInstance(obj));
+        }
 
-			if (obj is Asn1Sequence)
-            {
-                return new MacData((Asn1Sequence) obj);
-            }
+        public static MacData GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return new MacData(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
 
-			throw new ArgumentException("Unknown object in factory: " + Platform.GetTypeName(obj), "obj");
-		}
+        private readonly DigestInfo m_digInfo;
+        private readonly Asn1OctetString m_salt;
+        private readonly DerInteger m_iterationCount;
 
-		private MacData(
-            Asn1Sequence seq)
+        private MacData(Asn1Sequence seq)
         {
-            this.digInfo = DigestInfo.GetInstance(seq[0]);
-            this.salt = ((Asn1OctetString) seq[1]).GetOctets();
+            int count = seq.Count, pos = 0;
+            if (count < 2 || count > 3)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
+
+            m_digInfo = DigestInfo.GetInstance(seq[pos++]);
+            m_salt = Asn1OctetString.GetInstance(seq[pos++]);
+            m_iterationCount = Asn1Utilities.ReadOptional(seq, ref pos, DerInteger.GetOptional) ?? DerInteger.One;
 
-			if (seq.Count == 3)
-            {
-                this.iterationCount = ((DerInteger) seq[2]).Value;
-            }
-            else
-            {
-                this.iterationCount = BigInteger.One;
-            }
+            if (pos != count)
+                throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
         }
 
-		public MacData(
-            DigestInfo	digInfo,
-            byte[]		salt,
-            int			iterationCount)
+        public MacData(DigestInfo digInfo, byte[] salt, int iterationCount)
         {
-            this.digInfo = digInfo;
-            this.salt = (byte[]) salt.Clone();
-            this.iterationCount = BigInteger.ValueOf(iterationCount);
+            m_digInfo = digInfo ?? throw new ArgumentNullException(nameof(digInfo));
+            m_salt = new DerOctetString(salt);
+            m_iterationCount = new DerInteger(iterationCount);
         }
 
-		public DigestInfo Mac
-		{
-			get { return digInfo; }
-		}
+        public DigestInfo Mac => m_digInfo;
 
-		public byte[] GetSalt()
-        {
-            return (byte[]) salt.Clone();
-        }
+        public byte[] GetSalt() => (byte[])m_salt.GetOctets().Clone();
 
-		public BigInteger IterationCount
-		{
-			get { return iterationCount; }
-		}
+        public BigInteger IterationCount => m_iterationCount.Value;
 
 		/**
 		 * <pre>
@@ -83,14 +66,9 @@ namespace Org.BouncyCastle.Asn1.Pkcs
 		 */
 		public override Asn1Object ToAsn1Object()
         {
-			Asn1EncodableVector v = new Asn1EncodableVector(digInfo, new DerOctetString(salt));
-
-			if (!iterationCount.Equals(BigInteger.One))
-			{
-				v.Add(new DerInteger(iterationCount));
-			}
-
-			return new DerSequence(v);
+            return m_iterationCount.HasValue(1)
+                ?  new DerSequence(m_digInfo, m_salt)
+                :  new DerSequence(m_digInfo, m_salt, m_iterationCount);
         }
     }
 }
diff --git a/crypto/src/asn1/pkcs/PBEParameter.cs b/crypto/src/asn1/pkcs/PBEParameter.cs
index 31d9ad1f3..1fa518e1a 100644
--- a/crypto/src/asn1/pkcs/PBEParameter.cs
+++ b/crypto/src/asn1/pkcs/PBEParameter.cs
@@ -4,12 +4,9 @@ using Org.BouncyCastle.Math;
 
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
-	public class PbeParameter
+    public class PbeParameter
 		: Asn1Encodable
 	{
-		private readonly Asn1OctetString	salt;
-		private readonly DerInteger			iterationCount;
-
         public static PbeParameter GetInstance(object obj)
         {
             if (obj == null)
@@ -19,34 +16,34 @@ namespace Org.BouncyCastle.Asn1.Pkcs
             return new PbeParameter(Asn1Sequence.GetInstance(obj));
         }
 
-		private PbeParameter(Asn1Sequence seq)
+        public static PbeParameter GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return new PbeParameter(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
+        private readonly Asn1OctetString m_salt;
+        private readonly DerInteger m_iterationCount;
+
+        private PbeParameter(Asn1Sequence seq)
 		{
-			if (seq.Count != 2)
-				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+            int count = seq.Count;
+            if (count != 2)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-			salt = Asn1OctetString.GetInstance(seq[0]);
-			iterationCount = DerInteger.GetInstance(seq[1]);
+			m_salt = Asn1OctetString.GetInstance(seq[0]);
+			m_iterationCount = DerInteger.GetInstance(seq[1]);
 		}
 
 		public PbeParameter(byte[] salt, int iterationCount)
 		{
-			this.salt = new DerOctetString(salt);
-			this.iterationCount = new DerInteger(iterationCount);
+			m_salt = new DerOctetString(salt);
+			m_iterationCount = new DerInteger(iterationCount);
 		}
 
-		public byte[] GetSalt()
-		{
-			return salt.GetOctets();
-		}
+		public byte[] GetSalt() => m_salt.GetOctets();
 
-		public BigInteger IterationCount
-		{
-			get { return iterationCount.Value; }
-		}
+		public BigInteger IterationCount => m_iterationCount.Value;
 
-		public override Asn1Object ToAsn1Object()
-		{
-			return new DerSequence(salt, iterationCount);
-		}
+		public override Asn1Object ToAsn1Object() => new DerSequence(m_salt, m_iterationCount);
 	}
 }
diff --git a/crypto/src/asn1/pkcs/PBES2Parameters.cs b/crypto/src/asn1/pkcs/PBES2Parameters.cs
index 7d8a91ffa..0741fa8c1 100644
--- a/crypto/src/asn1/pkcs/PBES2Parameters.cs
+++ b/crypto/src/asn1/pkcs/PBES2Parameters.cs
@@ -1,63 +1,51 @@
 using System;
 
+using Org.BouncyCastle.Asn1.X509;
+
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
     public class PbeS2Parameters
         : Asn1Encodable
     {
-        private readonly KeyDerivationFunc func;
-        private readonly EncryptionScheme scheme;
-
         public static PbeS2Parameters GetInstance(object obj)
         {
             if (obj == null)
                 return null;
-            PbeS2Parameters existing = obj as PbeS2Parameters;
-            if (existing != null)
-                return existing;
+            if (obj is PbeS2Parameters pbeS2Parameters)
+                return pbeS2Parameters;
             return new PbeS2Parameters(Asn1Sequence.GetInstance(obj));
         }
 
-        public PbeS2Parameters(KeyDerivationFunc keyDevFunc, EncryptionScheme encScheme)
+        public static PbeS2Parameters GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
         {
-            this.func = keyDevFunc;
-            this.scheme = encScheme;
+            return new PbeS2Parameters(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
+        private readonly KeyDerivationFunc m_func;
+        private readonly EncryptionScheme m_scheme;
+
         private PbeS2Parameters(Asn1Sequence seq)
         {
-            if (seq.Count != 2)
-                throw new ArgumentException("Wrong number of elements in sequence", "seq");
-
-            Asn1Sequence funcSeq = (Asn1Sequence)seq[0].ToAsn1Object();
-
-            // TODO Not sure if this special case is really necessary/appropriate
-            if (funcSeq[0].Equals(PkcsObjectIdentifiers.IdPbkdf2))
-            {
-                func = new KeyDerivationFunc(PkcsObjectIdentifiers.IdPbkdf2,
-                    Pbkdf2Params.GetInstance(funcSeq[1]));
-            }
-            else
-            {
-                func = new KeyDerivationFunc(funcSeq);
-            }
-
-            scheme = EncryptionScheme.GetInstance(seq[1]);
-        }
+            int count = seq.Count;
+            if (count != 2)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-        public KeyDerivationFunc KeyDerivationFunc
-        {
-            get { return func; }
-        }
+            AlgorithmIdentifier func = AlgorithmIdentifier.GetInstance(seq[0]);
+            m_func = new KeyDerivationFunc(func.Algorithm, func.Parameters);
 
-        public EncryptionScheme EncryptionScheme
-        {
-            get { return scheme; }
+            m_scheme = EncryptionScheme.GetInstance(seq[1]);
         }
 
-        public override Asn1Object ToAsn1Object()
+        public PbeS2Parameters(KeyDerivationFunc keyDevFunc, EncryptionScheme encScheme)
         {
-            return new DerSequence(func, scheme);
+            m_func = keyDevFunc ?? throw new ArgumentNullException(nameof(keyDevFunc));
+            m_scheme = encScheme ?? throw new ArgumentNullException(nameof(encScheme));
         }
+
+        public KeyDerivationFunc KeyDerivationFunc => m_func;
+
+        public EncryptionScheme EncryptionScheme => m_scheme;
+
+        public override Asn1Object ToAsn1Object() => new DerSequence(m_func, m_scheme);
     }
 }
diff --git a/crypto/src/asn1/pkcs/PBKDF2Params.cs b/crypto/src/asn1/pkcs/PBKDF2Params.cs
index 13f469c6c..210d673e5 100644
--- a/crypto/src/asn1/pkcs/PBKDF2Params.cs
+++ b/crypto/src/asn1/pkcs/PBKDF2Params.cs
@@ -2,136 +2,98 @@ using System;
 
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Math;
-using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
     public class Pbkdf2Params
         : Asn1Encodable
     {
-        private static AlgorithmIdentifier algid_hmacWithSHA1 = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdHmacWithSha1, DerNull.Instance);
+        public static readonly AlgorithmIdentifier DefaultPrf = new AlgorithmIdentifier(
+            PkcsObjectIdentifiers.IdHmacWithSha1, DerNull.Instance);
 
-        private readonly Asn1OctetString     octStr;
-        private readonly DerInteger          iterationCount, keyLength;
-        private readonly AlgorithmIdentifier prf;
-
-        public static Pbkdf2Params GetInstance(
-            object obj)
+        public static Pbkdf2Params GetInstance(object obj)
         {
-            if (obj == null || obj is Pbkdf2Params)
-                return (Pbkdf2Params)obj;
-
-            if (obj is Asn1Sequence)
-                return new Pbkdf2Params((Asn1Sequence)obj);
+            if (obj == null)
+                return null;
+            if (obj is Pbkdf2Params pbkdf2Params)
+                return pbkdf2Params;
+#pragma warning disable CS0618 // Type or member is obsolete
+            return new Pbkdf2Params(Asn1Sequence.GetInstance(obj));
+#pragma warning restore CS0618 // Type or member is obsolete
+        }
 
-            throw new ArgumentException("Unknown object in factory: " + Platform.GetTypeName(obj), "obj");
+        public static Pbkdf2Params GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+#pragma warning disable CS0618 // Type or member is obsolete
+            return new Pbkdf2Params(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+#pragma warning restore CS0618 // Type or member is obsolete
         }
 
-        public Pbkdf2Params(
-            Asn1Sequence seq)
+        private readonly Asn1OctetString m_octStr;
+        private readonly DerInteger m_iterationCount, m_keyLength;
+        private readonly AlgorithmIdentifier m_prf;
+
+        [Obsolete("Use 'GetInstance' instead")]
+        public Pbkdf2Params(Asn1Sequence seq)
         {
-            if (seq.Count < 2 || seq.Count > 4)
-                throw new ArgumentException("Wrong number of elements in sequence", "seq");
+            int count = seq.Count, pos = 0;
+            if (count < 2 || count > 4)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-            this.octStr = (Asn1OctetString)seq[0];
-            this.iterationCount = (DerInteger)seq[1];
+            m_octStr = Asn1OctetString.GetInstance(seq[pos++]);
+            m_iterationCount = DerInteger.GetInstance(seq[pos++]);
+            m_keyLength = Asn1Utilities.ReadOptional(seq, ref pos, DerInteger.GetOptional);
+            m_prf = Asn1Utilities.ReadOptional(seq, ref pos, AlgorithmIdentifier.GetOptional) ?? DefaultPrf;
 
-            Asn1Encodable kl = null, d = null;
-            if (seq.Count > 3)
-            {
-                kl = seq[2];
-                d = seq[3];
-            }
-            else if (seq.Count > 2)
-            {
-                if (seq[2] is DerInteger)
-                {
-                    kl = seq[2];
-                }
-                else
-                {
-                    d = seq[2];
-                }
-            }
-            if (kl != null)
-            {
-                keyLength = (DerInteger)kl;
-            }
-            if (d != null)
-            {
-                prf = AlgorithmIdentifier.GetInstance(d);
-            }
+            if (pos != count)
+                throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
         }
 
-        public Pbkdf2Params(
-            byte[] salt,
-            int iterationCount)
+        public Pbkdf2Params(byte[] salt, int iterationCount)
+            : this(salt, iterationCount, prf: null)
         {
-            this.octStr = new DerOctetString(salt);
-            this.iterationCount = new DerInteger(iterationCount);
         }
 
-        public Pbkdf2Params(
-            byte[]  salt,
-            int     iterationCount,
-            int     keyLength)
-            : this(salt, iterationCount)
+        public Pbkdf2Params(byte[] salt, int iterationCount, int keyLength)
+            : this(salt, iterationCount, keyLength, prf: null)
         {
-            this.keyLength = new DerInteger(keyLength);
         }
 
-        public Pbkdf2Params(
-            byte[] salt,
-            int iterationCount,
-            int keyLength,
-            AlgorithmIdentifier prf)
-            : this(salt, iterationCount, keyLength)
+        public Pbkdf2Params(byte[] salt, int iterationCount, AlgorithmIdentifier prf)
         {
-            this.prf = prf;
+            m_octStr = new DerOctetString(salt);
+            m_iterationCount = new DerInteger(iterationCount);
+            m_keyLength = null;
+            m_prf = prf ?? DefaultPrf;
         }
 
-        public Pbkdf2Params(
-            byte[] salt,
-            int iterationCount,
-            AlgorithmIdentifier prf)
-            : this(salt, iterationCount)
+        public Pbkdf2Params(byte[] salt, int iterationCount, int keyLength, AlgorithmIdentifier prf)
         {
-            this.prf = prf;
+            m_octStr = new DerOctetString(salt);
+            m_iterationCount = new DerInteger(iterationCount);
+            m_keyLength = new DerInteger(keyLength);
+            m_prf = prf ?? DefaultPrf;
         }
 
-        public byte[] GetSalt()
-        {
-            return octStr.GetOctets();
-        }
+        public byte[] GetSalt() => m_octStr.GetOctets();
 
-        public BigInteger IterationCount
-        {
-            get { return iterationCount.Value; }
-        }
+        public BigInteger IterationCount => m_iterationCount.Value;
 
-        public BigInteger KeyLength
-        {
-            get { return keyLength == null ? null : keyLength.Value; }
-        }
+        public BigInteger KeyLength => m_keyLength?.Value;
 
-        public bool IsDefaultPrf
-        {
-            get { return prf == null || prf.Equals(algid_hmacWithSHA1); }
-        }
+        public bool IsDefaultPrf => DefaultPrf.Equals(m_prf);
 
-        public AlgorithmIdentifier Prf
-        {
-            get { return prf != null ? prf : algid_hmacWithSHA1; }
-        }
+        public AlgorithmIdentifier Prf => m_prf;
 
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(octStr, iterationCount);
-            v.AddOptional(keyLength);
+            Asn1EncodableVector v = new Asn1EncodableVector(4);
+            v.Add(m_octStr, m_iterationCount);
+            v.AddOptional(m_keyLength);
 
             if (!IsDefaultPrf)
             {
-                v.Add(prf);
+                v.Add(m_prf);
             }
 
             return new DerSequence(v);
diff --git a/crypto/src/asn1/pkcs/PKCS12PBEParams.cs b/crypto/src/asn1/pkcs/PKCS12PBEParams.cs
index b41c289d8..d237d49a2 100644
--- a/crypto/src/asn1/pkcs/PKCS12PBEParams.cs
+++ b/crypto/src/asn1/pkcs/PKCS12PBEParams.cs
@@ -1,63 +1,49 @@
 using System;
 
 using Org.BouncyCastle.Math;
-using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
     public class Pkcs12PbeParams
         : Asn1Encodable
     {
-        private readonly DerInteger iterations;
-        private readonly Asn1OctetString iv;
-
-		public Pkcs12PbeParams(
-            byte[]	salt,
-            int		iterations)
+        public static Pkcs12PbeParams GetInstance(object obj)
         {
-            this.iv = new DerOctetString(salt);
-            this.iterations = new DerInteger(iterations);
+            if (obj == null)
+                return null;
+            if (obj is Pkcs12PbeParams pkcs12PbeParams)
+                return pkcs12PbeParams;
+            return new Pkcs12PbeParams(Asn1Sequence.GetInstance(obj));
         }
 
-		private Pkcs12PbeParams(
-            Asn1Sequence seq)
+        public static Pkcs12PbeParams GetInstance(Asn1TaggedObject tagged, bool declaredExplicit)
         {
-			if (seq.Count != 2)
-				throw new ArgumentException("Wrong number of elements in sequence", "seq");
-
-			iv = Asn1OctetString.GetInstance(seq[0]);
-            iterations = DerInteger.GetInstance(seq[1]);
+            return new Pkcs12PbeParams(Asn1Sequence.GetInstance(tagged, declaredExplicit));
         }
 
-		public static Pkcs12PbeParams GetInstance(
-            object obj)
-        {
-            if (obj is Pkcs12PbeParams)
-            {
-                return (Pkcs12PbeParams) obj;
-            }
-
-			if (obj is Asn1Sequence)
-            {
-                return new Pkcs12PbeParams((Asn1Sequence) obj);
-            }
-
-			throw new ArgumentException("Unknown object in factory: " + Platform.GetTypeName(obj), "obj");
-		}
+        private readonly Asn1OctetString m_iv;
+        private readonly DerInteger m_iterations;
 
-		public BigInteger Iterations
-		{
-			get { return iterations.Value; }
-		}
-
-		public byte[] GetIV()
+        private Pkcs12PbeParams(Asn1Sequence seq)
         {
-            return iv.GetOctets();
+            int count = seq.Count;
+            if (count != 2)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
+
+            m_iv = Asn1OctetString.GetInstance(seq[0]);
+            m_iterations = DerInteger.GetInstance(seq[1]);
         }
 
-		public override Asn1Object ToAsn1Object()
+        public Pkcs12PbeParams(byte[] salt, int iterations)
         {
-			return new DerSequence(iv, iterations);
+            m_iv = new DerOctetString(salt);
+            m_iterations = new DerInteger(iterations);
         }
+
+        public BigInteger Iterations => m_iterations.Value;
+
+        public byte[] GetIV() => m_iv.GetOctets();
+
+        public override Asn1Object ToAsn1Object() => new DerSequence(m_iv, m_iterations);
     }
 }
diff --git a/crypto/src/asn1/pkcs/Pfx.cs b/crypto/src/asn1/pkcs/Pfx.cs
index 67d69a5ae..42ddfbfdd 100644
--- a/crypto/src/asn1/pkcs/Pfx.cs
+++ b/crypto/src/asn1/pkcs/Pfx.cs
@@ -1,8 +1,5 @@
 using System;
 
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Math;
-
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
     /**
@@ -13,51 +10,51 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     {
         public static Pfx GetInstance(object obj)
         {
-            if (obj is Pfx)
-                return (Pfx)obj;
             if (obj == null)
                 return null;
+            if (obj is Pfx pfx)
+                return pfx;
             return new Pfx(Asn1Sequence.GetInstance(obj));
         }
 
-        private readonly ContentInfo contentInfo;
-        private readonly MacData macData;
+        public static Pfx GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return new Pfx(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
+        private readonly ContentInfo m_contentInfo;
+        private readonly MacData m_macData;
 
 		private Pfx(Asn1Sequence seq)
         {
+            int count = seq.Count;
+            if (count < 2 || count > 3)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
+
             DerInteger version = DerInteger.GetInstance(seq[0]);
             if (!version.HasValue(3))
                 throw new ArgumentException("wrong version for PFX PDU");
 
-            this.contentInfo = ContentInfo.GetInstance(seq[1]);
+            m_contentInfo = ContentInfo.GetInstance(seq[1]);
 
-            if (seq.Count == 3)
-            {
-                this.macData = MacData.GetInstance(seq[2]);
-            }
+            m_macData = count <= 2 ? null : MacData.GetInstance(seq[2]);
         }
 
 		public Pfx(ContentInfo contentInfo, MacData macData)
         {
-            this.contentInfo = contentInfo;
-            this.macData = macData;
+            m_contentInfo = contentInfo ?? throw new ArgumentNullException(nameof(contentInfo));
+            m_macData = macData;
         }
 
-		public ContentInfo AuthSafe
-		{
-			get { return contentInfo; }
-		}
+        public ContentInfo AuthSafe => m_contentInfo;
 
-		public MacData MacData
-		{
-			get { return macData; }
-		}
+        public MacData MacData => m_macData;
 
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(DerInteger.Three, contentInfo);
-            v.AddOptional(macData);
-            return new BerSequence(v);
+            return m_macData == null
+                ?  new BerSequence(DerInteger.Three, m_contentInfo)
+                :  new BerSequence(DerInteger.Three, m_contentInfo, m_macData);
         }
     }
 }
diff --git a/crypto/src/asn1/pkcs/PrivateKeyInfo.cs b/crypto/src/asn1/pkcs/PrivateKeyInfo.cs
index 9535dbcae..7397b7061 100644
--- a/crypto/src/asn1/pkcs/PrivateKeyInfo.cs
+++ b/crypto/src/asn1/pkcs/PrivateKeyInfo.cs
@@ -1,8 +1,6 @@
 using System;
 
 using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Math;
-using Org.BouncyCastle.Utilities.Collections;
 
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
@@ -46,166 +44,115 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     public class PrivateKeyInfo
         : Asn1Encodable
     {
-        private readonly DerInteger version;
-        private readonly AlgorithmIdentifier privateKeyAlgorithm;
-        private readonly Asn1OctetString privateKey;
-        private readonly Asn1Set attributes;
-        private readonly DerBitString publicKey;
-
-        public static PrivateKeyInfo GetInstance(Asn1TaggedObject obj, bool explicitly)
-        {
-            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
-        }
-
-        public static PrivateKeyInfo GetInstance(
-            object obj)
+        public static PrivateKeyInfo GetInstance(object obj)
         {
             if (obj == null)
                 return null;
-            if (obj is PrivateKeyInfo)
-                return (PrivateKeyInfo)obj;
+            if (obj is PrivateKeyInfo privateKeyInfo)
+                return privateKeyInfo;
             return new PrivateKeyInfo(Asn1Sequence.GetInstance(obj));
         }
 
-        private static int GetVersionValue(DerInteger version)
-        {
-            BigInteger bigValue = version.Value;
-            if (bigValue.CompareTo(BigInteger.Zero) < 0 || bigValue.CompareTo(BigInteger.One) > 0)
-                throw new ArgumentException("invalid version for private key info", "version");
-
-            return bigValue.IntValue;
-        }
-
-        public PrivateKeyInfo(
-            AlgorithmIdentifier privateKeyAlgorithm,
-            Asn1Encodable privateKey)
-            : this(privateKeyAlgorithm, privateKey, null, null)
-        {
-        }
-
-        public PrivateKeyInfo(
-            AlgorithmIdentifier privateKeyAlgorithm,
-            Asn1Encodable privateKey,
-            Asn1Set attributes)
-            : this(privateKeyAlgorithm, privateKey, attributes, null)
+        public static PrivateKeyInfo GetInstance(Asn1TaggedObject obj, bool explicitly)
         {
+            return new PrivateKeyInfo(Asn1Sequence.GetInstance(obj, explicitly));
         }
 
-        public PrivateKeyInfo(
-            AlgorithmIdentifier privateKeyAlgorithm,
-            Asn1Encodable privateKey,
-            Asn1Set attributes,
-            byte[] publicKey)
-        {
-            this.version = new DerInteger(publicKey != null ? BigInteger.One : BigInteger.Zero);
-            this.privateKeyAlgorithm = privateKeyAlgorithm;
-            this.privateKey = new DerOctetString(privateKey);
-            this.attributes = attributes;
-            this.publicKey = publicKey == null ? null : new DerBitString(publicKey);
-        }
+        private readonly DerInteger m_version;
+        private readonly AlgorithmIdentifier m_privateKeyAlgorithm;
+        private readonly Asn1OctetString m_privateKey;
+        private readonly Asn1Set m_attributes;
+        private readonly DerBitString m_publicKey;
 
         private PrivateKeyInfo(Asn1Sequence seq)
         {
-            var e = seq.GetEnumerator();
+            int count = seq.Count, pos = 0;
+            if (count < 3 || count > 5)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-            this.version = DerInteger.GetInstance(CollectionUtilities.RequireNext(e));
+            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);
 
-            int versionValue = GetVersionValue(version);
+            if (pos != count)
+                throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
 
-            this.privateKeyAlgorithm = AlgorithmIdentifier.GetInstance(CollectionUtilities.RequireNext(e));
-            this.privateKey = Asn1OctetString.GetInstance(CollectionUtilities.RequireNext(e));
+            int versionValue = GetVersionValue(m_version);
 
-            int lastTag = -1;
-            while (e.MoveNext())
-            {
-                Asn1TaggedObject tagged = (Asn1TaggedObject)e.Current;
-
-                int tag = tagged.TagNo;
-                if (tag <= lastTag)
-                    throw new ArgumentException("invalid optional field in private key info", "seq");
-
-                lastTag = tag;
-
-                switch (tag)
-                {
-                case 0:
-                {
-                    this.attributes = Asn1Set.GetInstance(tagged, false);
-                    break;
-                }
-                case 1:
-                {
-                    if (versionValue < 1)
-                        throw new ArgumentException("'publicKey' requires version v2(1) or later", "seq");
-
-                    this.publicKey = DerBitString.GetInstance(tagged, false);
-                    break;
-                }
-                default:
-                {
-                    throw new ArgumentException("unknown optional field in private key info", "seq");
-                }
-                }
-            }
+            if (m_publicKey != null && versionValue < 1)
+                throw new ArgumentException("'publicKey' requires version v2(1) or later", nameof(seq));
         }
 
-        public virtual DerInteger Version
+        public PrivateKeyInfo(AlgorithmIdentifier privateKeyAlgorithm, Asn1Encodable privateKey)
+            : this(privateKeyAlgorithm, privateKey, null, null)
         {
-            get { return version; }
         }
 
-        public virtual Asn1Set Attributes
+        public PrivateKeyInfo(AlgorithmIdentifier privateKeyAlgorithm, Asn1Encodable privateKey, Asn1Set attributes)
+            : this(privateKeyAlgorithm, privateKey, attributes, null)
         {
-            get { return attributes; }
         }
 
-        /// <summary>Return true if a public key is present, false otherwise.</summary>
-        public virtual bool HasPublicKey
+        public PrivateKeyInfo(AlgorithmIdentifier privateKeyAlgorithm, Asn1Encodable privateKey, Asn1Set attributes,
+            byte[] publicKey)
         {
-            get { return publicKey != null; }
+            m_version = new DerInteger(publicKey != null ? 1 : 0);
+            m_privateKeyAlgorithm = privateKeyAlgorithm ?? throw new ArgumentNullException(nameof(privateKeyAlgorithm));
+            m_privateKey = new DerOctetString(privateKey);
+            m_attributes = attributes;
+            m_publicKey = publicKey == null ? null : new DerBitString(publicKey);
         }
 
-        public virtual AlgorithmIdentifier PrivateKeyAlgorithm
-        {
-            get { return privateKeyAlgorithm; }
-        }
+        public virtual DerInteger Version => m_version;
 
-        public virtual Asn1OctetString PrivateKey => privateKey;
+        public virtual Asn1Set Attributes => m_attributes;
+
+        /// <summary>Return true if a public key is present, false otherwise.</summary>
+        public virtual bool HasPublicKey => m_publicKey != null;
+
+        public virtual AlgorithmIdentifier PrivateKeyAlgorithm => m_privateKeyAlgorithm;
+
+        public virtual Asn1OctetString PrivateKey => m_privateKey;
 
         [Obsolete("Use 'PrivateKey' instead")]
-        public virtual Asn1OctetString PrivateKeyData
-        {
-            get { return privateKey; }
-        }
+        public virtual Asn1OctetString PrivateKeyData => m_privateKey;
 
-        public virtual int PrivateKeyLength => privateKey.GetOctetsLength();
+        public virtual int PrivateKeyLength => m_privateKey.GetOctetsLength();
 
-        public virtual Asn1Object ParsePrivateKey()
-        {
-            return Asn1Object.FromByteArray(privateKey.GetOctets());
-        }
+        public virtual Asn1Object ParsePrivateKey() => Asn1Object.FromByteArray(m_privateKey.GetOctets());
 
         /// <summary>For when the public key is an ASN.1 encoding.</summary>
         public virtual Asn1Object ParsePublicKey()
         {
-            return publicKey == null ? null : Asn1Object.FromByteArray(publicKey.GetOctets());
+            return m_publicKey == null ? null : Asn1Object.FromByteArray(m_publicKey.GetOctets());
         }
 
-        public virtual DerBitString PublicKey => publicKey;
+        public virtual DerBitString PublicKey => m_publicKey;
 
         /// <summary>Return the public key as a raw bit string.</summary>
         [Obsolete("Use 'PublicKey' instead")]
-        public virtual DerBitString PublicKeyData
-        {
-            get { return publicKey; }
-        }
+        public virtual DerBitString PublicKeyData => m_publicKey;
 
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(version, privateKeyAlgorithm, privateKey);
-            v.AddOptionalTagged(false, 0, attributes);
-            v.AddOptionalTagged(false, 1, publicKey);
+            Asn1EncodableVector v = new Asn1EncodableVector(5);
+            v.Add(m_version, m_privateKeyAlgorithm, m_privateKey);
+            v.AddOptionalTagged(false, 0, m_attributes);
+            v.AddOptionalTagged(false, 1, m_publicKey);
             return new DerSequence(v);
         }
+
+        private static int GetVersionValue(DerInteger version)
+        {
+            if (version.TryGetIntPositiveValueExact(out int value))
+            {
+                if (value >= 0 && value <= 1)
+                    return value;
+            }
+
+            throw new ArgumentException("Invalid version for PrivateKeyInfo", nameof(version));
+        }
     }
 }
diff --git a/crypto/src/asn1/pkcs/RC2CBCParameter.cs b/crypto/src/asn1/pkcs/RC2CBCParameter.cs
index c1f09a088..f38695f50 100644
--- a/crypto/src/asn1/pkcs/RC2CBCParameter.cs
+++ b/crypto/src/asn1/pkcs/RC2CBCParameter.cs
@@ -8,67 +8,56 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     public class RC2CbcParameter
         : Asn1Encodable
     {
-        internal DerInteger			version;
-        internal Asn1OctetString	iv;
-
-		public static RC2CbcParameter GetInstance(
-            object obj)
+		public static RC2CbcParameter GetInstance(object obj)
         {
-            if (obj is Asn1Sequence)
-            {
-                return new RC2CbcParameter((Asn1Sequence) obj);
-            }
-
-			throw new ArgumentException("Unknown object in factory: " + Platform.GetTypeName(obj), "obj");
+            if (obj == null)
+                return null;
+            if (obj is RC2CbcParameter rc2CbcParameter)
+                return rc2CbcParameter;
+            return new RC2CbcParameter(Asn1Sequence.GetInstance(obj));
 		}
 
-		public RC2CbcParameter(
-            byte[] iv)
-        {
-            this.iv = new DerOctetString(iv);
-        }
+        private readonly DerInteger m_version;
+        private readonly Asn1OctetString m_iv;
 
-		public RC2CbcParameter(
-            int		parameterVersion,
-            byte[]	iv)
+        private RC2CbcParameter(Asn1Sequence seq)
         {
-            this.version = new DerInteger(parameterVersion);
-            this.iv = new DerOctetString(iv);
-        }
+            int count = seq.Count, pos = 0;
+            if (count < 1 || count > 2)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-		private RC2CbcParameter(
-            Asn1Sequence seq)
-        {
-            if (seq.Count == 1)
-            {
-                iv = (Asn1OctetString)seq[0];
-            }
-            else
-            {
-                version = (DerInteger)seq[0];
-                iv = (Asn1OctetString)seq[1];
-            }
+            m_version = Asn1Utilities.ReadOptional(seq, ref pos, DerInteger.GetOptional);
+            m_iv = Asn1OctetString.GetInstance(seq[pos++]);
+
+            if (pos != count)
+                throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
         }
 
-		public BigInteger RC2ParameterVersion
+        public RC2CbcParameter(byte[] iv)
         {
-            get
-            {
-				return version == null ? null : version.Value;
-            }
+            m_version = null;
+            m_iv = new DerOctetString(iv);
         }
 
-		public byte[] GetIV()
+		public RC2CbcParameter(int parameterVersion, byte[] iv)
         {
-			return Arrays.Clone(iv.GetOctets());
+            m_version = new DerInteger(parameterVersion);
+            m_iv = new DerOctetString(iv);
         }
 
+        public BigInteger RC2ParameterVersion => m_version?.Value;
+
+        public DerInteger RC2ParameterVersionData => m_version;
+
+        public Asn1OctetString IV => m_iv;
+
+        public byte[] GetIV() => Arrays.Clone(m_iv.GetOctets());
+
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(2);
-            v.AddOptional(version);
-            v.Add(iv);
-            return new DerSequence(v);
+            return m_version == null
+                ?  new DerSequence(m_iv)
+                :  new DerSequence(m_version, m_iv);
         }
     }
 }
diff --git a/crypto/src/asn1/pkcs/RSAESOAEPparams.cs b/crypto/src/asn1/pkcs/RSAESOAEPparams.cs
index 988b230c8..3490509e7 100644
--- a/crypto/src/asn1/pkcs/RSAESOAEPparams.cs
+++ b/crypto/src/asn1/pkcs/RSAESOAEPparams.cs
@@ -2,103 +2,86 @@ using System;
 
 using Org.BouncyCastle.Asn1.Oiw;
 using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
-	public class RsaesOaepParameters
+    public class RsaesOaepParameters
 		: Asn1Encodable
 	{
-		private AlgorithmIdentifier hashAlgorithm;
-		private AlgorithmIdentifier maskGenAlgorithm;
-		private AlgorithmIdentifier pSourceAlgorithm;
-
-		public readonly static AlgorithmIdentifier DefaultHashAlgorithm = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
-		public readonly static AlgorithmIdentifier DefaultMaskGenFunction = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, DefaultHashAlgorithm);
-		public readonly static AlgorithmIdentifier DefaultPSourceAlgorithm = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[0]));
-
-		public static RsaesOaepParameters GetInstance(
-			object obj)
-		{
-			if (obj is RsaesOaepParameters)
-			{
-				return (RsaesOaepParameters)obj;
-			}
-			else if (obj is Asn1Sequence)
-			{
-				return new RsaesOaepParameters((Asn1Sequence)obj);
-			}
-
-			throw new ArgumentException("Unknown object in factory: " + Platform.GetTypeName(obj), "obj");
-		}
-
-		/**
+		public static readonly AlgorithmIdentifier DefaultHashAlgorithm = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
+		public static readonly AlgorithmIdentifier DefaultMaskGenAlgorithm = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, DefaultHashAlgorithm);
+        [Obsolete("Use 'DefaultMaskGenAlgorithm' instead")]
+        public static readonly AlgorithmIdentifier DefaultMaskGenFunction = DefaultMaskGenAlgorithm;
+        public static readonly AlgorithmIdentifier DefaultPSourceAlgorithm = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[0]));
+
+        public static RsaesOaepParameters GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is RsaesOaepParameters rsaesOaepParameters)
+                return rsaesOaepParameters;
+#pragma warning disable CS0618 // Type or member is obsolete
+            return new RsaesOaepParameters(Asn1Sequence.GetInstance(obj));
+#pragma warning restore CS0618 // Type or member is obsolete
+        }
+
+        public static RsaesOaepParameters GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+#pragma warning disable CS0618 // Type or member is obsolete
+            return new RsaesOaepParameters(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+#pragma warning restore CS0618 // Type or member is obsolete
+        }
+
+        private readonly AlgorithmIdentifier m_hashAlgorithm;
+        private readonly AlgorithmIdentifier m_maskGenAlgorithm;
+        private readonly AlgorithmIdentifier m_pSourceAlgorithm;
+
+        [Obsolete("Use 'GetInstance' instead")]
+        public RsaesOaepParameters(Asn1Sequence seq)
+        {
+            int count = seq.Count, pos = 0;
+            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)
+				?? DefaultHashAlgorithm;
+
+            m_maskGenAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, AlgorithmIdentifier.GetInstance)
+                ?? DefaultMaskGenAlgorithm;
+
+            m_pSourceAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, AlgorithmIdentifier.GetInstance)
+                ?? DefaultPSourceAlgorithm;
+
+            if (pos != count)
+                throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
+        }
+
+        /**
 		 * The default version
 		 */
-		public RsaesOaepParameters()
-		    : this(DefaultHashAlgorithm, DefaultMaskGenFunction, DefaultPSourceAlgorithm)
+        public RsaesOaepParameters()
+		    : this(DefaultHashAlgorithm, DefaultMaskGenAlgorithm, DefaultPSourceAlgorithm)
 		{ 
 		}
 
-		public RsaesOaepParameters(
-			AlgorithmIdentifier hashAlgorithm,
-			AlgorithmIdentifier maskGenAlgorithm)
-		    : this(hashAlgorithm, maskGenAlgorithm, DefaultPSourceAlgorithm)
-		{
-		}
+        public RsaesOaepParameters(AlgorithmIdentifier hashAlgorithm, AlgorithmIdentifier maskGenAlgorithm)
+            : this(hashAlgorithm, maskGenAlgorithm, DefaultPSourceAlgorithm)
+        {
+        }
 
-		public RsaesOaepParameters(
-			AlgorithmIdentifier hashAlgorithm,
-			AlgorithmIdentifier maskGenAlgorithm,
-			AlgorithmIdentifier pSourceAlgorithm)
-		{
-			this.hashAlgorithm = hashAlgorithm;
-			this.maskGenAlgorithm = maskGenAlgorithm;
-			this.pSourceAlgorithm = pSourceAlgorithm;
-		}
+        public RsaesOaepParameters(AlgorithmIdentifier hashAlgorithm, AlgorithmIdentifier maskGenAlgorithm,
+            AlgorithmIdentifier pSourceAlgorithm)
+        {
+            m_hashAlgorithm = hashAlgorithm;
+            m_maskGenAlgorithm = maskGenAlgorithm;
+            m_pSourceAlgorithm = pSourceAlgorithm;
+        }
 
-		public RsaesOaepParameters(
-			Asn1Sequence seq)
-		{
-			hashAlgorithm = DefaultHashAlgorithm;
-			maskGenAlgorithm = DefaultMaskGenFunction;
-			pSourceAlgorithm = DefaultPSourceAlgorithm;
+		public AlgorithmIdentifier HashAlgorithm => m_hashAlgorithm;
 
-			for (int i = 0; i != seq.Count; i++)
-			{
-				Asn1TaggedObject o = (Asn1TaggedObject)seq[i];
-
-				switch (o.TagNo)
-				{
-					case 0:
-						hashAlgorithm = AlgorithmIdentifier.GetInstance(o, true);
-						break;
-					case 1:
-						maskGenAlgorithm = AlgorithmIdentifier.GetInstance(o, true);
-						break;
-					case 2:
-						pSourceAlgorithm = AlgorithmIdentifier.GetInstance(o, true);
-						break;
-					default:
-						throw new ArgumentException("unknown tag");
-				}
-			}
-		}
+		public AlgorithmIdentifier MaskGenAlgorithm => m_maskGenAlgorithm;
 
-		public AlgorithmIdentifier HashAlgorithm
-		{
-			get { return hashAlgorithm; }
-		}
-
-		public AlgorithmIdentifier MaskGenAlgorithm
-		{
-			get { return maskGenAlgorithm; }
-		}
-
-		public AlgorithmIdentifier PSourceAlgorithm
-		{
-			get { return pSourceAlgorithm; }
-		}
+		public AlgorithmIdentifier PSourceAlgorithm => m_pSourceAlgorithm;
 
 		/**
 		 * <pre>
@@ -130,19 +113,19 @@ namespace Org.BouncyCastle.Asn1.Pkcs
 		{
 			Asn1EncodableVector v = new Asn1EncodableVector(3);
 
-			if (!hashAlgorithm.Equals(DefaultHashAlgorithm))
+			if (!DefaultHashAlgorithm.Equals(m_hashAlgorithm))
 			{
-				v.Add(new DerTaggedObject(true, 0, hashAlgorithm));
+				v.Add(new DerTaggedObject(true, 0, m_hashAlgorithm));
 			}
 
-			if (!maskGenAlgorithm.Equals(DefaultMaskGenFunction))
+			if (!DefaultMaskGenAlgorithm.Equals(m_maskGenAlgorithm))
 			{
-				v.Add(new DerTaggedObject(true, 1, maskGenAlgorithm));
+				v.Add(new DerTaggedObject(true, 1, m_maskGenAlgorithm));
 			}
 
-			if (!pSourceAlgorithm.Equals(DefaultPSourceAlgorithm))
+			if (!DefaultPSourceAlgorithm.Equals(m_pSourceAlgorithm))
 			{
-				v.Add(new DerTaggedObject(true, 2, pSourceAlgorithm));
+				v.Add(new DerTaggedObject(true, 2, m_pSourceAlgorithm));
 			}
 
 			return new DerSequence(v);
diff --git a/crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs b/crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs
index 0e7911163..afd642255 100644
--- a/crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs
+++ b/crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs
@@ -7,29 +7,29 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     public class RsaPrivateKeyStructure
         : Asn1Encodable
     {
-        private readonly BigInteger modulus;
-        private readonly BigInteger publicExponent;
-        private readonly BigInteger privateExponent;
-        private readonly BigInteger prime1;
-        private readonly BigInteger prime2;
-        private readonly BigInteger exponent1;
-        private readonly BigInteger exponent2;
-        private readonly BigInteger coefficient;
-
-        public static RsaPrivateKeyStructure GetInstance(Asn1TaggedObject obj, bool isExplicit)
-        {
-            return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
-        }
-
         public static RsaPrivateKeyStructure GetInstance(object obj)
         {
             if (obj == null)
                 return null;
-            if (obj is RsaPrivateKeyStructure)
-                return (RsaPrivateKeyStructure)obj;
+            if (obj is RsaPrivateKeyStructure rsaPrivateKeyStructure)
+                return rsaPrivateKeyStructure;
             return new RsaPrivateKeyStructure(Asn1Sequence.GetInstance(obj));
         }
 
+        public static RsaPrivateKeyStructure GetInstance(Asn1TaggedObject obj, bool isExplicit)
+        {
+            return new RsaPrivateKeyStructure(Asn1Sequence.GetInstance(obj, isExplicit));
+        }
+
+        private readonly BigInteger m_modulus;
+        private readonly BigInteger m_publicExponent;
+        private readonly BigInteger m_privateExponent;
+        private readonly BigInteger m_prime1;
+        private readonly BigInteger m_prime2;
+        private readonly BigInteger m_exponent1;
+        private readonly BigInteger m_exponent2;
+        private readonly BigInteger m_coefficient;
+
         public RsaPrivateKeyStructure(
             BigInteger modulus,
             BigInteger publicExponent,
@@ -40,71 +40,51 @@ namespace Org.BouncyCastle.Asn1.Pkcs
             BigInteger exponent2,
             BigInteger coefficient)
         {
-            this.modulus = modulus;
-            this.publicExponent = publicExponent;
-            this.privateExponent = privateExponent;
-            this.prime1 = prime1;
-            this.prime2 = prime2;
-            this.exponent1 = exponent1;
-            this.exponent2 = exponent2;
-            this.coefficient = coefficient;
+            m_modulus = modulus ?? throw new ArgumentNullException(nameof(modulus));
+            m_publicExponent = publicExponent ?? throw new ArgumentNullException(nameof(publicExponent));
+            m_privateExponent = privateExponent ?? throw new ArgumentNullException(nameof(privateExponent));
+            m_prime1 = prime1 ?? throw new ArgumentNullException(nameof(prime1));
+            m_prime2 = prime2 ?? throw new ArgumentNullException(nameof(prime2));
+            m_exponent1 = exponent1 ?? throw new ArgumentNullException(nameof(exponent1));
+            m_exponent2 = exponent2 ?? throw new ArgumentNullException(nameof(exponent2));
+            m_coefficient = coefficient ?? throw new ArgumentNullException(nameof(coefficient));
         }
 
         private RsaPrivateKeyStructure(Asn1Sequence seq)
         {
-            BigInteger version = ((DerInteger)seq[0]).Value;
-            if (version.IntValue != 0)
+            int count = seq.Count;
+            if (count != 9)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
+
+            var version = DerInteger.GetInstance(seq[0]);
+            m_modulus = DerInteger.GetInstance(seq[1]).Value;
+            m_publicExponent = DerInteger.GetInstance(seq[2]).Value;
+            m_privateExponent = DerInteger.GetInstance(seq[3]).Value;
+            m_prime1 = DerInteger.GetInstance(seq[4]).Value;
+            m_prime2 = DerInteger.GetInstance(seq[5]).Value;
+            m_exponent1 = DerInteger.GetInstance(seq[6]).Value;
+            m_exponent2 = DerInteger.GetInstance(seq[7]).Value;
+            m_coefficient = DerInteger.GetInstance(seq[8]).Value;
+
+            if (!version.HasValue(0))
                 throw new ArgumentException("wrong version for RSA private key");
-
-            modulus = ((DerInteger)seq[1]).Value;
-            publicExponent = ((DerInteger)seq[2]).Value;
-            privateExponent = ((DerInteger)seq[3]).Value;
-            prime1 = ((DerInteger)seq[4]).Value;
-            prime2 = ((DerInteger)seq[5]).Value;
-            exponent1 = ((DerInteger)seq[6]).Value;
-            exponent2 = ((DerInteger)seq[7]).Value;
-            coefficient = ((DerInteger)seq[8]).Value;
         }
 
-        public BigInteger Modulus
-        {
-            get { return modulus; }
-        }
+        public BigInteger Modulus => m_modulus;
 
-        public BigInteger PublicExponent
-        {
-            get { return publicExponent; }
-        }
+        public BigInteger PublicExponent => m_publicExponent;
 
-        public BigInteger PrivateExponent
-        {
-            get { return privateExponent; }
-        }
+        public BigInteger PrivateExponent => m_privateExponent;
 
-        public BigInteger Prime1
-        {
-            get { return prime1; }
-        }
+        public BigInteger Prime1 => m_prime1;
 
-        public BigInteger Prime2
-        {
-            get { return prime2; }
-        }
+        public BigInteger Prime2 => m_prime2;
 
-        public BigInteger Exponent1
-        {
-            get { return exponent1; }
-        }
+        public BigInteger Exponent1 => m_exponent1;
 
-        public BigInteger Exponent2
-        {
-            get { return exponent2; }
-        }
+        public BigInteger Exponent2 => m_exponent2;
 
-        public BigInteger Coefficient
-        {
-            get { return coefficient; }
-        }
+        public BigInteger Coefficient => m_coefficient;
 
         /**
          * This outputs the key in Pkcs1v2 format.
@@ -129,14 +109,14 @@ namespace Org.BouncyCastle.Asn1.Pkcs
         {
             return new DerSequence(
                 DerInteger.Zero, // version
-                new DerInteger(Modulus),
-                new DerInteger(PublicExponent),
-                new DerInteger(PrivateExponent),
-                new DerInteger(Prime1),
-                new DerInteger(Prime2),
-                new DerInteger(Exponent1),
-                new DerInteger(Exponent2),
-                new DerInteger(Coefficient));
+                new DerInteger(m_modulus),
+                new DerInteger(m_publicExponent),
+                new DerInteger(m_privateExponent),
+                new DerInteger(m_prime1),
+                new DerInteger(m_prime2),
+                new DerInteger(m_exponent1),
+                new DerInteger(m_exponent2),
+                new DerInteger(m_coefficient));
         }
     }
 }
diff --git a/crypto/src/asn1/pkcs/RSASSAPSSparams.cs b/crypto/src/asn1/pkcs/RSASSAPSSparams.cs
index ead2faa73..f7a9d6956 100644
--- a/crypto/src/asn1/pkcs/RSASSAPSSparams.cs
+++ b/crypto/src/asn1/pkcs/RSASSAPSSparams.cs
@@ -2,113 +2,92 @@ using System;
 
 using Org.BouncyCastle.Asn1.Oiw;
 using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
-	public class RsassaPssParameters
+    public class RsassaPssParameters
 		: Asn1Encodable
 	{
-		private AlgorithmIdentifier hashAlgorithm;
-		private AlgorithmIdentifier maskGenAlgorithm;
-		private DerInteger saltLength;
-		private DerInteger trailerField;
-
 		public readonly static AlgorithmIdentifier DefaultHashAlgorithm = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
-		public readonly static AlgorithmIdentifier DefaultMaskGenFunction = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, DefaultHashAlgorithm);
+        public readonly static AlgorithmIdentifier DefaultMaskGenAlgorithm = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, DefaultHashAlgorithm);
+        [Obsolete("Use 'DefaultMaskGenAlgorithm' instead")]
+        public readonly static AlgorithmIdentifier DefaultMaskGenFunction = DefaultMaskGenAlgorithm;
 		public readonly static DerInteger DefaultSaltLength = new DerInteger(20);
 		public readonly static DerInteger DefaultTrailerField = DerInteger.One;
 
-		public static RsassaPssParameters GetInstance(
-			object obj)
+        public static RsassaPssParameters GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is RsassaPssParameters rsassaPssParameters)
+                return rsassaPssParameters;
+#pragma warning disable CS0618 // Type or member is obsolete
+            return new RsassaPssParameters(Asn1Sequence.GetInstance(obj));
+#pragma warning restore CS0618 // Type or member is obsolete
+        }
+
+        public static RsassaPssParameters GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+#pragma warning disable CS0618 // Type or member is obsolete
+            return new RsassaPssParameters(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+#pragma warning restore CS0618 // Type or member is obsolete
+        }
+
+        private readonly AlgorithmIdentifier m_hashAlgorithm;
+        private readonly AlgorithmIdentifier m_maskGenAlgorithm;
+        private readonly DerInteger m_saltLength;
+        private readonly DerInteger m_trailerField;
+
+        [Obsolete("Use 'GetInstance' instead")]
+        public RsassaPssParameters(Asn1Sequence seq)
 		{
-			if (obj == null || obj is RsassaPssParameters)
-			{
-				return (RsassaPssParameters)obj;
-			}
+            int count = seq.Count, pos = 0;
+            if (count < 0 || count > 4)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-			if (obj is Asn1Sequence)
-			{
-				return new RsassaPssParameters((Asn1Sequence)obj);
-			}
+            m_hashAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, AlgorithmIdentifier.GetInstance)
+                ?? DefaultHashAlgorithm;
 
-			throw new ArgumentException("Unknown object in factory: " + Platform.GetTypeName(obj), "obj");
-		}
+            m_maskGenAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, AlgorithmIdentifier.GetInstance)
+                ?? DefaultMaskGenAlgorithm;
 
-		/**
-		 * The default version
-		 */
-		public RsassaPssParameters()
-		{
-			hashAlgorithm = DefaultHashAlgorithm;
-			maskGenAlgorithm = DefaultMaskGenFunction;
-			saltLength = DefaultSaltLength;
-			trailerField = DefaultTrailerField;
-		}
+            m_saltLength = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, true, DerInteger.GetInstance)
+                ?? DefaultSaltLength;
 
-		public RsassaPssParameters(
-			AlgorithmIdentifier hashAlgorithm,
-			AlgorithmIdentifier maskGenAlgorithm,
-			DerInteger saltLength,
-			DerInteger trailerField)
-		{
-			this.hashAlgorithm = hashAlgorithm;
-			this.maskGenAlgorithm = maskGenAlgorithm;
-			this.saltLength = saltLength;
-			this.trailerField = trailerField;
+            m_trailerField = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 3, true, DerInteger.GetInstance)
+                ?? DefaultTrailerField;
+
+            if (pos != count)
+                throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
 		}
 
-		public RsassaPssParameters(
-			Asn1Sequence seq)
-		{
-			hashAlgorithm = DefaultHashAlgorithm;
-			maskGenAlgorithm = DefaultMaskGenFunction;
-			saltLength = DefaultSaltLength;
-			trailerField = DefaultTrailerField;
+        /**
+		 * The default version
+		 */
+        public RsassaPssParameters()
+        {
+            m_hashAlgorithm = DefaultHashAlgorithm;
+            m_maskGenAlgorithm = DefaultMaskGenAlgorithm;
+            m_saltLength = DefaultSaltLength;
+            m_trailerField = DefaultTrailerField;
+        }
 
-			for (int i = 0; i != seq.Count; i++)
-			{
-				Asn1TaggedObject o = (Asn1TaggedObject)seq[i];
-
-				switch (o.TagNo)
-				{
-					case 0:
-						hashAlgorithm = AlgorithmIdentifier.GetInstance(o, true);
-						break;
-					case 1:
-						maskGenAlgorithm = AlgorithmIdentifier.GetInstance(o, true);
-						break;
-					case 2:
-						saltLength = DerInteger.GetInstance(o, true);
-						break;
-					case 3:
-						trailerField = DerInteger.GetInstance(o, true);
-						break;
-					default:
-						throw new ArgumentException("unknown tag");
-				}
-			}
-		}
+        public RsassaPssParameters(AlgorithmIdentifier hashAlgorithm, AlgorithmIdentifier maskGenAlgorithm,
+            DerInteger saltLength, DerInteger trailerField)
+        {
+            m_hashAlgorithm = hashAlgorithm ?? DefaultHashAlgorithm;
+            m_maskGenAlgorithm = maskGenAlgorithm ?? DefaultMaskGenAlgorithm;
+            m_saltLength = saltLength ?? DefaultSaltLength;
+            m_trailerField = trailerField ?? DefaultTrailerField;
+        }
 
-		public AlgorithmIdentifier HashAlgorithm
-		{
-			get { return hashAlgorithm; }
-		}
+		public AlgorithmIdentifier HashAlgorithm => m_hashAlgorithm;
 
-		public AlgorithmIdentifier MaskGenAlgorithm
-		{
-			get { return maskGenAlgorithm; }
-		}
+		public AlgorithmIdentifier MaskGenAlgorithm => m_maskGenAlgorithm;
 
-		public DerInteger SaltLength
-		{
-			get { return saltLength; }
-		}
+		public DerInteger SaltLength => m_saltLength;
 
-		public DerInteger TrailerField
-		{
-			get { return trailerField; }
-		}
+		public DerInteger TrailerField => m_trailerField;
 
 		/**
 		 * <pre>
@@ -140,24 +119,24 @@ namespace Org.BouncyCastle.Asn1.Pkcs
 		{
 			Asn1EncodableVector v = new Asn1EncodableVector(4);
 
-			if (!hashAlgorithm.Equals(DefaultHashAlgorithm))
+			if (!DefaultHashAlgorithm.Equals(m_hashAlgorithm))
 			{
-				v.Add(new DerTaggedObject(true, 0, hashAlgorithm));
+				v.Add(new DerTaggedObject(true, 0, m_hashAlgorithm));
 			}
 
-			if (!maskGenAlgorithm.Equals(DefaultMaskGenFunction))
+			if (!DefaultMaskGenAlgorithm.Equals(m_maskGenAlgorithm))
 			{
-				v.Add(new DerTaggedObject(true, 1, maskGenAlgorithm));
+				v.Add(new DerTaggedObject(true, 1, m_maskGenAlgorithm));
 			}
 
-			if (!saltLength.Equals(DefaultSaltLength))
+			if (!DefaultSaltLength.Equals(m_saltLength))
 			{
-				v.Add(new DerTaggedObject(true, 2, saltLength));
+				v.Add(new DerTaggedObject(true, 2, m_saltLength));
 			}
 
-			if (!trailerField.Equals(DefaultTrailerField))
+			if (!DefaultTrailerField.Equals(m_trailerField))
 			{
-				v.Add(new DerTaggedObject(true, 3, trailerField));
+				v.Add(new DerTaggedObject(true, 3, m_trailerField));
 			}
 
 			return new DerSequence(v);
diff --git a/crypto/src/asn1/pkcs/SafeBag.cs b/crypto/src/asn1/pkcs/SafeBag.cs
index 8b35a6717..9f8dbb8cc 100644
--- a/crypto/src/asn1/pkcs/SafeBag.cs
+++ b/crypto/src/asn1/pkcs/SafeBag.cs
@@ -1,7 +1,5 @@
 using System;
 
-using Org.BouncyCastle.Asn1;
-
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
     public class SafeBag
@@ -9,65 +7,60 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     {
         public static SafeBag GetInstance(object obj)
         {
-            if (obj is SafeBag)
-                return (SafeBag)obj;
             if (obj == null)
                 return null;
+            if (obj is SafeBag safeBag)
+                return safeBag;
             return new SafeBag(Asn1Sequence.GetInstance(obj));
         }
 
-        private readonly DerObjectIdentifier bagID;
-        private readonly Asn1Object bagValue;
-        private readonly Asn1Set bagAttributes;
+        public static SafeBag GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return new SafeBag(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
+        private readonly DerObjectIdentifier m_bagID;
+        private readonly Asn1Object m_bagValue;
+        private readonly Asn1Set m_bagAttributes;
 
-		public SafeBag(
-            DerObjectIdentifier	oid,
-            Asn1Object			obj)
+        private SafeBag(Asn1Sequence seq)
         {
-            this.bagID = oid;
-            this.bagValue = obj;
-            this.bagAttributes = null;
+            int count = seq.Count, pos = 0;
+            if (count < 2 || count > 3)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
+
+            m_bagID = DerObjectIdentifier.GetInstance(seq[pos++]);
+            m_bagValue = Asn1TaggedObject.GetInstance(seq[pos++], Asn1Tags.ContextSpecific, 0)
+                .GetExplicitBaseObject().ToAsn1Object();
+            m_bagAttributes = Asn1Utilities.ReadOptional(seq, ref pos, Asn1Set.GetOptional);
+
+            if (pos != count)
+                throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
         }
 
-		public SafeBag(
-            DerObjectIdentifier	oid,
-            Asn1Object			obj,
-            Asn1Set				bagAttributes)
+        public SafeBag(DerObjectIdentifier oid, Asn1Object obj)
+            : this(oid, obj, null)
         {
-            this.bagID = oid;
-            this.bagValue = obj;
-            this.bagAttributes = bagAttributes;
         }
 
-		private SafeBag(Asn1Sequence seq)
+        public SafeBag(DerObjectIdentifier oid, Asn1Object obj, Asn1Set bagAttributes)
         {
-            this.bagID = (DerObjectIdentifier)seq[0];
-            this.bagValue = ((Asn1TaggedObject)seq[1]).GetExplicitBaseObject().ToAsn1Object();
-            if (seq.Count == 3)
-            {
-                this.bagAttributes = (Asn1Set)seq[2];
-            }
+            m_bagID = oid ?? throw new ArgumentNullException(nameof(oid));
+            m_bagValue = obj ?? throw new ArgumentNullException(nameof(obj));
+            m_bagAttributes = bagAttributes;
         }
 
-		public DerObjectIdentifier BagID
-		{
-			get { return bagID; }
-		}
+        public DerObjectIdentifier BagID => m_bagID;
 
-		public Asn1Object BagValue
-		{
-			get { return bagValue; }
-		}
+        public Asn1Object BagValue => m_bagValue;
 
-		public Asn1Set BagAttributes
-		{
-			get { return bagAttributes; }
-		}
+        public Asn1Set BagAttributes => m_bagAttributes;
 
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(bagID, new DerTaggedObject(0, bagValue));
-            v.AddOptional(bagAttributes);
+            Asn1EncodableVector v = new Asn1EncodableVector(3);
+            v.Add(m_bagID, new DerTaggedObject(0, m_bagValue));
+            v.AddOptional(m_bagAttributes);
             return new DerSequence(v);
         }
     }
diff --git a/crypto/src/asn1/pkcs/SignedData.cs b/crypto/src/asn1/pkcs/SignedData.cs
index e309d9245..de9c758fb 100644
--- a/crypto/src/asn1/pkcs/SignedData.cs
+++ b/crypto/src/asn1/pkcs/SignedData.cs
@@ -8,111 +8,72 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     public class SignedData
         : Asn1Encodable
     {
-        private readonly DerInteger		version;
-        private readonly Asn1Set		digestAlgorithms;
-        private readonly ContentInfo	contentInfo;
-        private readonly Asn1Set		certificates;
-        private readonly Asn1Set		crls;
-        private readonly Asn1Set		signerInfos;
-
         public static SignedData GetInstance(object obj)
         {
             if (obj == null)
                 return null;
-            SignedData existing = obj as SignedData;
-            if (existing != null)
-                return existing;
+            if (obj is SignedData signedData)
+                return signedData;
             return new SignedData(Asn1Sequence.GetInstance(obj));
         }
 
-        public SignedData(
-            DerInteger        _version,
-            Asn1Set           _digestAlgorithms,
-            ContentInfo       _contentInfo,
-            Asn1Set           _certificates,
-            Asn1Set           _crls,
-            Asn1Set           _signerInfos)
+        public static SignedData GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
         {
-            version          = _version;
-            digestAlgorithms = _digestAlgorithms;
-            contentInfo      = _contentInfo;
-            certificates     = _certificates;
-            crls             = _crls;
-            signerInfos      = _signerInfos;
+            return new SignedData(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
-        private SignedData(
-            Asn1Sequence seq)
-        {
-            var e = seq.GetEnumerator();
-
-            e.MoveNext();
-            version = (DerInteger) e.Current;
-
-            e.MoveNext();
-            digestAlgorithms = (Asn1Set) e.Current;
+        private readonly DerInteger m_version;
+        private readonly Asn1Set m_digestAlgorithms;
+        private readonly ContentInfo m_contentInfo;
+        private readonly Asn1Set m_certificates;
+        private readonly Asn1Set m_crls;
+        private readonly Asn1Set m_signerInfos;
 
-            e.MoveNext();
-            contentInfo = ContentInfo.GetInstance(e.Current);
-
-            while (e.MoveNext())
-            {
-                Asn1Object o = e.Current.ToAsn1Object();
-
-                //
-                // an interesting feature of SignedData is that there appear to be varying implementations...
-                // for the moment we ignore anything which doesn't fit.
-                //
-                if (o is Asn1TaggedObject tagged)
-                {
-                    switch (tagged.TagNo)
-                    {
-                    case 0:
-                        certificates = Asn1Set.GetInstance(tagged, false);
-                        break;
-                    case 1:
-                        crls = Asn1Set.GetInstance(tagged, false);
-                        break;
-                    default:
-                        throw new ArgumentException("unknown tag value " + tagged.TagNo);
-                    }
-                }
-                else
-                {
-                    signerInfos = (Asn1Set) o;
-                }
-            }
-        }
-
-        public DerInteger Version
+        private SignedData(Asn1Sequence seq)
         {
-            get { return version; }
+            int count = seq.Count, pos = 0;
+            if (count < 4 || count > 6)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
+
+            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_signerInfos = Asn1Set.GetInstance(seq[pos++]);
+
+            if (pos != count)
+                throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
         }
 
-        public Asn1Set DigestAlgorithms
+        // TODO[api] Improve parameter names
+        public SignedData(
+            DerInteger _version,
+            Asn1Set _digestAlgorithms,
+            ContentInfo _contentInfo,
+            Asn1Set _certificates,
+            Asn1Set _crls,
+            Asn1Set _signerInfos)
         {
-            get { return digestAlgorithms; }
+            m_version = _version ?? throw new ArgumentNullException(nameof(_version));
+            m_digestAlgorithms = _digestAlgorithms ?? throw new ArgumentNullException(nameof(_digestAlgorithms));
+            m_contentInfo = _contentInfo ?? throw new ArgumentNullException(nameof(_contentInfo));
+            m_certificates = _certificates;
+            m_crls = _crls;
+            m_signerInfos = _signerInfos ?? throw new ArgumentNullException(nameof(_signerInfos));
         }
 
-        public ContentInfo ContentInfo
-        {
-            get { return contentInfo; }
-        }
+        public DerInteger Version => m_version;
 
-        public Asn1Set Certificates
-        {
-            get { return certificates; }
-        }
+        public Asn1Set DigestAlgorithms => m_digestAlgorithms;
 
-        public Asn1Set Crls
-        {
-            get { return crls; }
-        }
+        public ContentInfo ContentInfo => m_contentInfo;
 
-        public Asn1Set SignerInfos
-        {
-            get { return signerInfos; }
-        }
+        public Asn1Set Certificates => m_certificates;
+
+        public Asn1Set Crls => m_crls;
+
+        public Asn1Set SignerInfos => m_signerInfos;
 
         /**
          * Produce an object suitable for an Asn1OutputStream.
@@ -131,10 +92,11 @@ namespace Org.BouncyCastle.Asn1.Pkcs
          */
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(version, digestAlgorithms, contentInfo);
-            v.AddOptionalTagged(false, 0, certificates);
-            v.AddOptionalTagged(false, 1, crls);
-            v.Add(signerInfos);
+            Asn1EncodableVector v = new Asn1EncodableVector(6);
+            v.Add(m_version, m_digestAlgorithms, m_contentInfo);
+            v.AddOptionalTagged(false, 0, m_certificates);
+            v.AddOptionalTagged(false, 1, m_crls);
+            v.Add(m_signerInfos);
             return new BerSequence(v);
         }
     }
diff --git a/crypto/src/asn1/pkcs/SignerInfo.cs b/crypto/src/asn1/pkcs/SignerInfo.cs
index 532a564f3..01d9de98e 100644
--- a/crypto/src/asn1/pkcs/SignerInfo.cs
+++ b/crypto/src/asn1/pkcs/SignerInfo.cs
@@ -1,3 +1,5 @@
+using System;
+
 using Org.BouncyCastle.Asn1.X509;
 
 namespace Org.BouncyCastle.Asn1.Pkcs
@@ -8,97 +10,82 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     public class SignerInfo
         : Asn1Encodable
     {
-        private DerInteger              version;
-        private IssuerAndSerialNumber   issuerAndSerialNumber;
-        private AlgorithmIdentifier     digAlgorithm;
-        private Asn1Set                 authenticatedAttributes;
-        private AlgorithmIdentifier     digEncryptionAlgorithm;
-        private Asn1OctetString         encryptedDigest;
-        private Asn1Set                 unauthenticatedAttributes;
-
         public static SignerInfo GetInstance(object obj)
         {
             if (obj == null)
                 return null;
             if (obj is SignerInfo signerInfo)
                 return signerInfo;
+#pragma warning disable CS0618 // Type or member is obsolete
             return new SignerInfo(Asn1Sequence.GetInstance(obj));
+#pragma warning restore CS0618 // Type or member is obsolete
+        }
+
+        public static SignerInfo GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+#pragma warning disable CS0618 // Type or member is obsolete
+            return new SignerInfo(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+#pragma warning restore CS0618 // Type or member is obsolete
         }
 
-		public SignerInfo(
-            DerInteger              version,
-            IssuerAndSerialNumber   issuerAndSerialNumber,
-            AlgorithmIdentifier     digAlgorithm,
-            Asn1Set                 authenticatedAttributes,
-            AlgorithmIdentifier     digEncryptionAlgorithm,
-            Asn1OctetString         encryptedDigest,
-            Asn1Set                 unauthenticatedAttributes)
+        private readonly DerInteger m_version;
+        private readonly IssuerAndSerialNumber m_issuerAndSerialNumber;
+        private readonly AlgorithmIdentifier m_digAlgorithm;
+        private readonly Asn1Set m_authenticatedAttributes;
+        private readonly AlgorithmIdentifier m_digEncryptionAlgorithm;
+        private readonly Asn1OctetString m_encryptedDigest;
+        private readonly Asn1Set m_unauthenticatedAttributes;
+
+        [Obsolete("Use 'GetInstance' instead")]
+        public SignerInfo(Asn1Sequence seq)
         {
-            this.version = version;
-            this.issuerAndSerialNumber = issuerAndSerialNumber;
-            this.digAlgorithm = digAlgorithm;
-            this.authenticatedAttributes = authenticatedAttributes;
-            this.digEncryptionAlgorithm = digEncryptionAlgorithm;
-            this.encryptedDigest = encryptedDigest;
-            this.unauthenticatedAttributes = unauthenticatedAttributes;
+            int count = seq.Count, pos = 0;
+            if (count < 5 || count > 7)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
+
+            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_digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]);
+            m_encryptedDigest = Asn1OctetString.GetInstance(seq[pos++]);
+            m_unauthenticatedAttributes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetInstance);
+
+            if (pos != count)
+                throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
         }
 
-		public SignerInfo(
-            Asn1Sequence seq)
+        public SignerInfo(
+            DerInteger version,
+            IssuerAndSerialNumber issuerAndSerialNumber,
+            AlgorithmIdentifier digAlgorithm,
+            Asn1Set authenticatedAttributes,
+            AlgorithmIdentifier digEncryptionAlgorithm,
+            Asn1OctetString encryptedDigest,
+            Asn1Set unauthenticatedAttributes)
         {
-            var e = seq.GetEnumerator();
-
-			e.MoveNext();
-            version = (DerInteger) e.Current;
-
-			e.MoveNext();
-            issuerAndSerialNumber = IssuerAndSerialNumber.GetInstance(e.Current);
-
-			e.MoveNext();
-            digAlgorithm = AlgorithmIdentifier.GetInstance(e.Current);
-
-			e.MoveNext();
-            var obj = e.Current;
-
-			if (obj is Asn1TaggedObject tagged)
-            {
-                authenticatedAttributes = Asn1Set.GetInstance(tagged, false);
-
-				e.MoveNext();
-                digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(e.Current);
-            }
-            else
-            {
-                authenticatedAttributes = null;
-                digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(obj);
-            }
-
-			e.MoveNext();
-            encryptedDigest = Asn1OctetString.GetInstance(e.Current);
-
-			if (e.MoveNext())
-            {
-                unauthenticatedAttributes = Asn1Set.GetInstance((Asn1TaggedObject)e.Current, false);
-            }
-            else
-            {
-                unauthenticatedAttributes = null;
-            }
+            m_version = version ?? throw new ArgumentNullException(nameof(version));
+            m_issuerAndSerialNumber = issuerAndSerialNumber ?? throw new ArgumentNullException(nameof(issuerAndSerialNumber));
+            m_digAlgorithm = digAlgorithm ?? throw new ArgumentNullException(nameof(digAlgorithm));
+            m_authenticatedAttributes = authenticatedAttributes;
+            m_digEncryptionAlgorithm = digEncryptionAlgorithm ?? throw new ArgumentNullException(nameof(digEncryptionAlgorithm));
+            m_encryptedDigest = encryptedDigest ?? throw new ArgumentNullException(nameof(encryptedDigest));
+            m_unauthenticatedAttributes = unauthenticatedAttributes;
         }
 
-		public DerInteger Version { get { return version; } }
+        public DerInteger Version => m_version;
 
-		public IssuerAndSerialNumber IssuerAndSerialNumber { get { return issuerAndSerialNumber; } }
+		public IssuerAndSerialNumber IssuerAndSerialNumber => m_issuerAndSerialNumber;
 
-		public Asn1Set AuthenticatedAttributes { get { return authenticatedAttributes; } }
+        public Asn1Set AuthenticatedAttributes => m_authenticatedAttributes;
 
-		public AlgorithmIdentifier DigestAlgorithm { get { return digAlgorithm; } }
+        public AlgorithmIdentifier DigestAlgorithm => m_digAlgorithm;
 
-		public Asn1OctetString EncryptedDigest { get { return encryptedDigest; } }
+		public Asn1OctetString EncryptedDigest => m_encryptedDigest;
 
-		public AlgorithmIdentifier DigestEncryptionAlgorithm { get { return digEncryptionAlgorithm; } }
+		public AlgorithmIdentifier DigestEncryptionAlgorithm => m_digEncryptionAlgorithm;
 
-		public Asn1Set UnauthenticatedAttributes { get { return unauthenticatedAttributes; } }
+		public Asn1Set UnauthenticatedAttributes => m_unauthenticatedAttributes;
 
 		/**
          * Produce an object suitable for an Asn1OutputStream.
@@ -122,10 +109,11 @@ namespace Org.BouncyCastle.Asn1.Pkcs
          */
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(version, issuerAndSerialNumber, digAlgorithm);
-            v.AddOptionalTagged(false, 0, authenticatedAttributes);
-            v.Add(digEncryptionAlgorithm, encryptedDigest);
-            v.AddOptionalTagged(false, 1, unauthenticatedAttributes);
+            Asn1EncodableVector v = new Asn1EncodableVector(7);
+            v.Add(m_version, m_issuerAndSerialNumber, m_digAlgorithm);
+            v.AddOptionalTagged(false, 0, m_authenticatedAttributes);
+            v.Add(m_digEncryptionAlgorithm, m_encryptedDigest);
+            v.AddOptionalTagged(false, 1, m_unauthenticatedAttributes);
             return new DerSequence(v);
         }
     }