summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2023-02-06 15:40:40 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2023-02-06 15:40:40 +0700
commit32ceae264dc39331174d9db71fe38948648c7989 (patch)
tree180846e6d6f42b56659a71facae5c7d582a2e14f
parentMisc. refactoring after bc-fips-csharp updates (diff)
downloadBouncyCastle.NET-ed25519-32ceae264dc39331174d9db71fe38948648c7989.tar.xz
New tagged object methods and refactoring
-rw-r--r--crypto/src/asn1/ASN1TaggedObjectParser.cs6
-rw-r--r--crypto/src/asn1/Asn1TaggedObject.cs131
-rw-r--r--crypto/src/asn1/Asn1Utilities.cs108
-rw-r--r--crypto/src/asn1/BERTaggedObjectParser.cs10
-rw-r--r--crypto/src/asn1/BerTaggedObject.cs2
-rw-r--r--crypto/src/asn1/DLTaggedObject.cs2
-rw-r--r--crypto/src/asn1/DerTaggedObject.cs2
7 files changed, 192 insertions, 69 deletions
diff --git a/crypto/src/asn1/ASN1TaggedObjectParser.cs b/crypto/src/asn1/ASN1TaggedObjectParser.cs
index 0b53b6abf..3e3acda6e 100644
--- a/crypto/src/asn1/ASN1TaggedObjectParser.cs
+++ b/crypto/src/asn1/ASN1TaggedObjectParser.cs
@@ -10,10 +10,16 @@ namespace Org.BouncyCastle.Asn1
 
 		int TagNo { get; }
 
+        // TODO[api]
+        //bool HasContextTag();
+
         bool HasContextTag(int tagNo);
 
         bool HasTag(int tagClass, int tagNo);
 
+        // TODO[api]
+        //bool HasTagClass(int tagClass);
+
         /// <exception cref="IOException"/>
         IAsn1Convertible ParseBaseUniversal(bool declaredExplicit, int baseTagNo);
 
diff --git a/crypto/src/asn1/Asn1TaggedObject.cs b/crypto/src/asn1/Asn1TaggedObject.cs
index 63ab6a5d0..314170750 100644
--- a/crypto/src/asn1/Asn1TaggedObject.cs
+++ b/crypto/src/asn1/Asn1TaggedObject.cs
@@ -41,52 +41,56 @@ namespace Org.BouncyCastle.Asn1
                 }
                 catch (IOException e)
                 {
-                    throw new ArgumentException("failed to construct tagged object from byte[]: " + e.Message);
+                    throw new ArgumentException("failed to construct tagged object from byte[]", nameof(obj), e);
                 }
             }
 
-            throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj");
+            throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), nameof(obj));
 		}
 
         public static Asn1TaggedObject GetInstance(object obj, int tagClass)
         {
-            if (obj == null)
-                throw new ArgumentNullException(nameof(obj));
-
-            Asn1TaggedObject taggedObject = GetInstance(obj);
-            if (tagClass != taggedObject.TagClass)
-                throw new ArgumentException("unexpected tag in GetInstance: " + Asn1Utilities.GetTagText(taggedObject));
-
-            return taggedObject;
+            return Asn1Utilities.CheckTagClass(CheckInstance(obj), tagClass);
         }
 
         public static Asn1TaggedObject GetInstance(object obj, int tagClass, int tagNo)
         {
-            if (obj == null)
-                throw new ArgumentNullException(nameof(obj));
+            return Asn1Utilities.CheckTag(CheckInstance(obj), tagClass, tagNo);
+        }
 
-            Asn1TaggedObject taggedObject = GetInstance(obj);
-            if (!taggedObject.HasTag(tagClass, tagNo))
-                throw new ArgumentException("unexpected tag in GetInstance: " + Asn1Utilities.GetTagText(taggedObject));
+        public static Asn1TaggedObject GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return Asn1Utilities.GetExplicitContextBaseTagged(CheckInstance(taggedObject, declaredExplicit));
+        }
 
-            return taggedObject;
+        public static Asn1TaggedObject GetInstance(Asn1TaggedObject taggedObject, int tagClass, bool declaredExplicit)
+        {
+            return Asn1Utilities.GetExplicitBaseTagged(CheckInstance(taggedObject, declaredExplicit), tagClass);
         }
 
-        public static Asn1TaggedObject GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        public static Asn1TaggedObject GetInstance(Asn1TaggedObject taggedObject, int tagClass, int tagNo,
+            bool declaredExplicit)
         {
-            if (Asn1Tags.ContextSpecific != taggedObject.TagClass)
-                throw new InvalidOperationException("this method only valid for CONTEXT_SPECIFIC tags");
+            return Asn1Utilities.GetExplicitBaseTagged(CheckInstance(taggedObject, declaredExplicit), tagClass, tagNo);
+        }
 
-            if (declaredExplicit)
-                return taggedObject.GetExplicitBaseTagged();
+        private static Asn1TaggedObject CheckInstance(object obj)
+        {
+            return GetInstance(obj ?? throw new ArgumentNullException(nameof(obj)));
+        }
 
-            throw new ArgumentException("this method not valid for implicitly tagged tagged objects");
+        private static Asn1TaggedObject CheckInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            if (!declaredExplicit)
+                throw new ArgumentException("this method not valid for implicitly tagged tagged objects");
+
+            return taggedObject ?? throw new ArgumentNullException(nameof(taggedObject));
         }
 
-        internal readonly int explicitness;
-        internal readonly int tagClass;
-        internal readonly int tagNo;
-        internal readonly Asn1Encodable obj;
+        internal readonly int m_explicitness;
+        internal readonly int m_tagClass;
+        internal readonly int m_tagNo;
+        internal readonly Asn1Encodable m_object;
 
 		/**
          * @param explicitly true if the object is explicitly tagged.
@@ -106,23 +110,23 @@ namespace Org.BouncyCastle.Asn1
         internal Asn1TaggedObject(int explicitness, int tagClass, int tagNo, Asn1Encodable obj)
         {
             if (null == obj)
-                throw new ArgumentNullException("obj");
+                throw new ArgumentNullException(nameof(obj));
             if (Asn1Tags.Universal == tagClass || (tagClass & Asn1Tags.Private) != tagClass)
-                throw new ArgumentException("invalid tag class: " + tagClass, "tagClass");
+                throw new ArgumentException("invalid tag class: " + tagClass, nameof(tagClass));
 
-            this.explicitness = (obj is IAsn1Choice) ? DeclaredExplicit : explicitness;
-            this.tagClass = tagClass;
-            this.tagNo = tagNo;
-            this.obj = obj;
+            m_explicitness = obj is IAsn1Choice ? DeclaredExplicit : explicitness;
+            m_tagClass = tagClass;
+            m_tagNo = tagNo;
+            m_object = obj;
         }
 
         protected override bool Asn1Equals(Asn1Object asn1Object)
         {
             Asn1TaggedObject that = asn1Object as Asn1TaggedObject;
-            if (null == that || this.tagNo != that.tagNo || this.tagClass != that.tagClass)
+            if (null == that || this.m_tagNo != that.m_tagNo || this.m_tagClass != that.m_tagClass)
                 return false;
 
-            if (this.explicitness != that.explicitness)
+            if (this.m_explicitness != that.m_explicitness)
             {
                 /*
                  * TODO This seems incorrect for some cases of implicit tags e.g. if one is a
@@ -132,8 +136,8 @@ namespace Org.BouncyCastle.Asn1
                     return false;
             }
 
-            Asn1Object p1 = this.obj.ToAsn1Object();
-            Asn1Object p2 = that.obj.ToAsn1Object();
+            Asn1Object p1 = this.m_object.ToAsn1Object();
+            Asn1Object p2 = that.m_object.ToAsn1Object();
 
             if (p1 == p2)
                 return true;
@@ -158,27 +162,31 @@ namespace Org.BouncyCastle.Asn1
 
 		protected override int Asn1GetHashCode()
 		{
-            return (tagClass * 7919) ^ tagNo ^ (IsExplicit() ? 0x0F : 0xF0) ^ obj.ToAsn1Object().CallAsn1GetHashCode();
+            return (m_tagClass * 7919) ^ m_tagNo ^ (IsExplicit() ? 0x0F : 0xF0) ^ m_object.ToAsn1Object().CallAsn1GetHashCode();
         }
 
-        public int TagClass
-        {
-            get { return tagClass; }
-        }
+        public int TagClass => m_tagClass;
+
+        public int TagNo => m_tagNo;
 
-		public int TagNo
+        public bool HasContextTag()
         {
-			get { return tagNo; }
+            return m_tagClass == Asn1Tags.ContextSpecific;
         }
 
         public bool HasContextTag(int tagNo)
         {
-            return this.tagClass == Asn1Tags.ContextSpecific && this.tagNo == tagNo;
+            return m_tagClass == Asn1Tags.ContextSpecific && m_tagNo == tagNo;
         }
 
         public bool HasTag(int tagClass, int tagNo)
         {
-            return this.tagClass == tagClass && this.tagNo == tagNo;
+            return m_tagClass == tagClass && m_tagNo == tagNo;
+        }
+
+        public bool HasTagClass(int tagClass)
+        {
+            return m_tagClass == tagClass;
         }
 
         /**
@@ -193,7 +201,7 @@ namespace Org.BouncyCastle.Asn1
         public bool IsExplicit()
         {
             // TODO New methods like 'IsKnownExplicit' etc. to distinguish uncertain cases?
-            switch (explicitness)
+            switch (m_explicitness)
             {
             case DeclaredExplicit:
             case ParsedExplicit:
@@ -205,7 +213,7 @@ namespace Org.BouncyCastle.Asn1
 
         internal bool IsParsed()
         {
-            switch (explicitness)
+            switch (m_explicitness)
             {
             case ParsedExplicit:
             case ParsedImplicit:
@@ -224,10 +232,9 @@ namespace Org.BouncyCastle.Asn1
          */
         public Asn1Object GetObject()
         {
-            if (Asn1Tags.ContextSpecific != TagClass)
-                throw new InvalidOperationException("this method only valid for CONTEXT_SPECIFIC tags");
+            Asn1Utilities.CheckTagClass(this, Asn1Tags.ContextSpecific);
 
-            return obj.ToAsn1Object();
+            return m_object.ToAsn1Object();
         }
 
         /**
@@ -238,7 +245,7 @@ namespace Org.BouncyCastle.Asn1
          */
         public Asn1Encodable GetBaseObject()
         {
-            return obj;
+            return m_object;
         }
 
         /**
@@ -252,7 +259,7 @@ namespace Org.BouncyCastle.Asn1
             if (!IsExplicit())
                 throw new InvalidOperationException("object implicit - explicit expected.");
 
-            return obj;
+            return m_object;
         }
 
         public Asn1TaggedObject GetExplicitBaseTagged()
@@ -260,22 +267,22 @@ namespace Org.BouncyCastle.Asn1
             if (!IsExplicit())
                 throw new InvalidOperationException("object implicit - explicit expected.");
 
-            return CheckedCast(obj.ToAsn1Object());
+            return CheckedCast(m_object.ToAsn1Object());
         }
 
         public Asn1TaggedObject GetImplicitBaseTagged(int baseTagClass, int baseTagNo)
         {
             if (Asn1Tags.Universal == baseTagClass || (baseTagClass & Asn1Tags.Private) != baseTagClass)
-                throw new ArgumentException("invalid base tag class: " + baseTagClass, "baseTagClass");
+                throw new ArgumentException("invalid base tag class: " + baseTagClass, nameof(baseTagClass));
 
-            switch (explicitness)
+            switch (m_explicitness)
             {
             case DeclaredExplicit:
                 throw new InvalidOperationException("object explicit - implicit expected.");
 
             case DeclaredImplicit:
             {
-                Asn1TaggedObject declared = CheckedCast(obj.ToAsn1Object());
+                Asn1TaggedObject declared = CheckedCast(m_object.ToAsn1Object());
                 return Asn1Utilities.CheckTag(declared, baseTagClass, baseTagNo);
             }
 
@@ -289,7 +296,7 @@ namespace Org.BouncyCastle.Asn1
         {
             Asn1UniversalType universalType = Asn1UniversalTypes.Get(tagNo);
             if (null == universalType)
-                throw new ArgumentException("unsupported UNIVERSAL tag number: " + tagNo, "tagNo");
+                throw new ArgumentException("unsupported UNIVERSAL tag number: " + tagNo, nameof(tagNo));
 
             return GetBaseUniversal(declaredExplicit, universalType);
         }
@@ -301,14 +308,14 @@ namespace Org.BouncyCastle.Asn1
                 if (!IsExplicit())
                     throw new InvalidOperationException("object explicit - implicit expected.");
 
-                return universalType.CheckedCast(obj.ToAsn1Object());
+                return universalType.CheckedCast(m_object.ToAsn1Object());
             }
 
-            if (DeclaredExplicit == explicitness)
+            if (DeclaredExplicit == m_explicitness)
                 throw new InvalidOperationException("object explicit - implicit expected.");
 
-            Asn1Object baseObject = obj.ToAsn1Object();
-            switch (explicitness)
+            Asn1Object baseObject = m_object.ToAsn1Object();
+            switch (m_explicitness)
             {
             case ParsedExplicit:
                 return universalType.FromImplicitConstructed(RebuildConstructed(baseObject));
@@ -360,7 +367,7 @@ namespace Org.BouncyCastle.Asn1
 
 		public override string ToString()
 		{
-            return Asn1Utilities.GetTagText(tagClass, tagNo) + obj;
+            return Asn1Utilities.GetTagText(m_tagClass, m_tagNo) + m_object;
 		}
 
         internal abstract string Asn1Encoding { get; }
diff --git a/crypto/src/asn1/Asn1Utilities.cs b/crypto/src/asn1/Asn1Utilities.cs
index 6ccdfc43a..07f8aad03 100644
--- a/crypto/src/asn1/Asn1Utilities.cs
+++ b/crypto/src/asn1/Asn1Utilities.cs
@@ -7,6 +7,28 @@ namespace Org.BouncyCastle.Asn1
 {
     public abstract class Asn1Utilities
     {
+        internal static Asn1TaggedObject CheckTagClass(Asn1TaggedObject taggedObject, int tagClass)
+        {
+            if (!taggedObject.HasTagClass(tagClass))
+            {
+                string expected = GetTagClassText(tagClass);
+                string found = GetTagClassText(taggedObject);
+                throw new InvalidOperationException("Expected " + expected + " tag but found " + found);
+            }
+            return taggedObject;
+        }
+
+        internal static Asn1TaggedObjectParser CheckTagClass(Asn1TaggedObjectParser taggedObjectParser, int tagClass)
+        {
+            if (taggedObjectParser.TagClass != tagClass)
+            {
+                string expected = GetTagClassText(tagClass);
+                string found = GetTagClassText(taggedObjectParser);
+                throw new InvalidOperationException("Expected " + expected + " tag but found " + found);
+            }
+            return taggedObjectParser;
+        }
+
         internal static Asn1TaggedObject CheckTag(Asn1TaggedObject taggedObject, int tagClass, int tagNo)
         {
             if (!taggedObject.HasTag(tagClass, tagNo))
@@ -48,6 +70,31 @@ namespace Org.BouncyCastle.Asn1
         }
 
 
+        public static string GetTagClassText(int tagClass)
+        {
+            switch (tagClass)
+            {
+            case Asn1Tags.Application:
+                return "APPLICATION";
+            case Asn1Tags.ContextSpecific:
+                return "CONTEXT";
+            case Asn1Tags.Private:
+                return "PRIVATE";
+            default:
+                return "UNIVERSAL";
+            }
+        }
+
+        public static string GetTagClassText(Asn1TaggedObject taggedObject)
+        {
+            return GetTagClassText(taggedObject.TagClass);
+        }
+
+        public static string GetTagClassText(Asn1TaggedObjectParser taggedObjectParser)
+        {
+            return GetTagClassText(taggedObjectParser.TagClass);
+        }
+
         internal static string GetTagText(Asn1Tag tag)
         {
             return GetTagText(tag.TagClass, tag.TagNo);
@@ -68,13 +115,13 @@ namespace Org.BouncyCastle.Asn1
             switch (tagClass)
             {
             case Asn1Tags.Application:
-                return "[APPLICATION " + tagNo + "]";
+                return string.Format("[APPLICATION {0}]", tagNo);
             case Asn1Tags.ContextSpecific:
-                return "[CONTEXT " + tagNo + "]";
+                return string.Format("[CONTEXT {0}]", tagNo);
             case Asn1Tags.Private:
-                return "[PRIVATE " + tagNo + "]";
+                return string.Format("[PRIVATE {0}]", tagNo);
             default:
-                return "[UNIVERSAL " + tagNo + "]";
+                return string.Format("[UNIVERSAL {0}]", tagNo);
             }
         }
 
@@ -111,16 +158,34 @@ namespace Org.BouncyCastle.Asn1
          * Wrappers for Asn1TaggedObject.GetExplicitBaseTagged
          */
 
+        public static Asn1TaggedObject GetExplicitBaseTagged(Asn1TaggedObject taggedObject, int tagClass)
+        {
+            return CheckTagClass(taggedObject, tagClass).GetExplicitBaseTagged();
+        }
+
         public static Asn1TaggedObject GetExplicitBaseTagged(Asn1TaggedObject taggedObject, int tagClass, int tagNo)
         {
             return CheckTag(taggedObject, tagClass, tagNo).GetExplicitBaseTagged();
         }
 
+        public static Asn1TaggedObject GetExplicitContextBaseTagged(Asn1TaggedObject taggedObject)
+        {
+            return GetExplicitBaseTagged(taggedObject, Asn1Tags.ContextSpecific);
+        }
+
         public static Asn1TaggedObject GetExplicitContextBaseTagged(Asn1TaggedObject taggedObject, int tagNo)
         {
             return GetExplicitBaseTagged(taggedObject, Asn1Tags.ContextSpecific, tagNo);
         }
 
+        public static Asn1TaggedObject TryGetExplicitBaseTagged(Asn1TaggedObject taggedObject, int tagClass)
+        {
+            if (!taggedObject.HasTagClass(tagClass))
+                return null;
+
+            return taggedObject.GetExplicitBaseTagged();
+        }
+
         public static Asn1TaggedObject TryGetExplicitBaseTagged(Asn1TaggedObject taggedObject, int tagClass, int tagNo)
         {
             if (!taggedObject.HasTag(tagClass, tagNo))
@@ -129,6 +194,11 @@ namespace Org.BouncyCastle.Asn1
             return taggedObject.GetExplicitBaseTagged();
         }
 
+        public static Asn1TaggedObject TryGetExplicitContextBaseTagged(Asn1TaggedObject taggedObject)
+        {
+            return TryGetExplicitBaseTagged(taggedObject, Asn1Tags.ContextSpecific);
+        }
+
         public static Asn1TaggedObject TryGetExplicitContextBaseTagged(Asn1TaggedObject taggedObject, int tagNo)
         {
             return TryGetExplicitBaseTagged(taggedObject, Asn1Tags.ContextSpecific, tagNo);
@@ -205,12 +275,25 @@ namespace Org.BouncyCastle.Asn1
 
         /// <exception cref="IOException"/>
         public static Asn1TaggedObjectParser ParseExplicitBaseTagged(Asn1TaggedObjectParser taggedObjectParser,
+            int tagClass)
+        {
+            return CheckTagClass(taggedObjectParser, tagClass).ParseExplicitBaseTagged();
+        }
+
+        /// <exception cref="IOException"/>
+        public static Asn1TaggedObjectParser ParseExplicitBaseTagged(Asn1TaggedObjectParser taggedObjectParser,
             int tagClass, int tagNo)
         {
             return CheckTag(taggedObjectParser, tagClass, tagNo).ParseExplicitBaseTagged();
         }
 
         /// <exception cref="IOException"/>
+        public static Asn1TaggedObjectParser ParseExplicitContextBaseTagged(Asn1TaggedObjectParser taggedObjectParser)
+        {
+            return ParseExplicitBaseTagged(taggedObjectParser, Asn1Tags.ContextSpecific);
+        }
+
+        /// <exception cref="IOException"/>
         public static Asn1TaggedObjectParser ParseExplicitContextBaseTagged(Asn1TaggedObjectParser taggedObjectParser,
             int tagNo)
         {
@@ -219,6 +302,16 @@ namespace Org.BouncyCastle.Asn1
 
         /// <exception cref="IOException"/>
         public static Asn1TaggedObjectParser TryParseExplicitBaseTagged(Asn1TaggedObjectParser taggedObjectParser,
+            int tagClass)
+        {
+            if (taggedObjectParser.TagClass != tagClass)
+                return null;
+
+            return taggedObjectParser.ParseExplicitBaseTagged();
+        }
+
+        /// <exception cref="IOException"/>
+        public static Asn1TaggedObjectParser TryParseExplicitBaseTagged(Asn1TaggedObjectParser taggedObjectParser,
             int tagClass, int tagNo)
         {
             if (!taggedObjectParser.HasTag(tagClass, tagNo))
@@ -229,6 +322,13 @@ namespace Org.BouncyCastle.Asn1
 
         /// <exception cref="IOException"/>
         public static Asn1TaggedObjectParser TryParseExplicitContextBaseTagged(
+            Asn1TaggedObjectParser taggedObjectParser)
+        {
+            return TryParseExplicitBaseTagged(taggedObjectParser, Asn1Tags.ContextSpecific);
+        }
+
+        /// <exception cref="IOException"/>
+        public static Asn1TaggedObjectParser TryParseExplicitContextBaseTagged(
             Asn1TaggedObjectParser taggedObjectParser, int tagNo)
         {
             return TryParseExplicitBaseTagged(taggedObjectParser, Asn1Tags.ContextSpecific, tagNo);
diff --git a/crypto/src/asn1/BERTaggedObjectParser.cs b/crypto/src/asn1/BERTaggedObjectParser.cs
index ecb4a4a13..b1a8cd896 100644
--- a/crypto/src/asn1/BERTaggedObjectParser.cs
+++ b/crypto/src/asn1/BERTaggedObjectParser.cs
@@ -32,6 +32,11 @@ namespace Org.BouncyCastle.Asn1
 			get { return m_tagNo; }
 		}
 
+        public bool HasContextTag()
+        {
+            return m_tagClass == Asn1Tags.ContextSpecific;
+        }
+
         public bool HasContextTag(int tagNo)
         {
             return m_tagClass == Asn1Tags.ContextSpecific && m_tagNo == tagNo;
@@ -42,6 +47,11 @@ namespace Org.BouncyCastle.Asn1
             return m_tagClass == tagClass && m_tagNo == tagNo;
         }
 
+        public bool HasTagClass(int tagClass)
+        {
+            return m_tagClass == tagClass;
+        }
+
         public virtual IAsn1Convertible ParseBaseUniversal(bool declaredExplicit, int baseTagNo)
         {
             if (declaredExplicit)
diff --git a/crypto/src/asn1/BerTaggedObject.cs b/crypto/src/asn1/BerTaggedObject.cs
index 4970b76f9..c200a74de 100644
--- a/crypto/src/asn1/BerTaggedObject.cs
+++ b/crypto/src/asn1/BerTaggedObject.cs
@@ -82,7 +82,7 @@ namespace Org.BouncyCastle.Asn1
 
         internal override Asn1TaggedObject ReplaceTag(int tagClass, int tagNo)
         {
-            return new BerTaggedObject(explicitness, tagClass, tagNo, obj);
+            return new BerTaggedObject(m_explicitness, tagClass, tagNo, m_object);
         }
     }
 }
diff --git a/crypto/src/asn1/DLTaggedObject.cs b/crypto/src/asn1/DLTaggedObject.cs
index c06dd8e87..30e3334e2 100644
--- a/crypto/src/asn1/DLTaggedObject.cs
+++ b/crypto/src/asn1/DLTaggedObject.cs
@@ -69,7 +69,7 @@ namespace Org.BouncyCastle.Asn1
 
         internal override Asn1TaggedObject ReplaceTag(int tagClass, int tagNo)
         {
-            return new DLTaggedObject(explicitness, tagClass, tagNo, obj);
+            return new DLTaggedObject(m_explicitness, tagClass, tagNo, m_object);
         }
     }
 }
diff --git a/crypto/src/asn1/DerTaggedObject.cs b/crypto/src/asn1/DerTaggedObject.cs
index 9d9997dc6..dbcc19760 100644
--- a/crypto/src/asn1/DerTaggedObject.cs
+++ b/crypto/src/asn1/DerTaggedObject.cs
@@ -76,7 +76,7 @@ namespace Org.BouncyCastle.Asn1
 
         internal override Asn1TaggedObject ReplaceTag(int tagClass, int tagNo)
         {
-            return new DerTaggedObject(explicitness, tagClass, tagNo, obj);
+            return new DerTaggedObject(m_explicitness, tagClass, tagNo, m_object);
         }
     }
 }