summaryrefslogtreecommitdiffstats
path: root/python/pyasn1/doc/tagging.html
diff options
context:
space:
mode:
Diffstat (limited to 'python/pyasn1/doc/tagging.html')
-rw-r--r--python/pyasn1/doc/tagging.html233
1 files changed, 233 insertions, 0 deletions
diff --git a/python/pyasn1/doc/tagging.html b/python/pyasn1/doc/tagging.html
new file mode 100644
index 000000000..187f1180d
--- /dev/null
+++ b/python/pyasn1/doc/tagging.html
@@ -0,0 +1,233 @@
+<html>
+<title>
+Tagging in PyASN1
+</title>
+<head>
+</head>
+<body>
+<center>
+<table width=60%>
+<tr>
+<td>
+<a name="1.2"></a>
+<h4>
+1.2 Tagging in PyASN1
+</h4>
+
+<p>
+In order to continue with the Constructed ASN.1 types, we will first have
+to introduce the concept of tagging (and its pyasn1 implementation), as
+some of the Constructed types rely upon the tagging feature.
+</p>
+
+<p>
+When a value is coming into an ASN.1-based system (received from a network
+or read from some storage), the receiving entity has to determine the
+type of the value to interpret and verify it accordingly.
+</p>
+
+<p>
+Historically, the first data serialization protocol introduced in
+ASN.1 was BER (Basic Encoding Rules). According to BER, any serialized
+value is packed into a triplet of (Type, Length, Value) where Type is a
+code that identifies the value (which is called <i>tag</i> in ASN.1),
+length is the number of bytes occupied by the value in its serialized form
+and value is ASN.1 value in a form suitable for serial transmission or storage.
+</p>
+
+<p>
+For that reason almost every ASN.1 type has a tag (which is actually a
+BER type) associated with it by default.
+</p>
+
+<p>
+An ASN.1 tag could be viewed as a tuple of three numbers:
+(Class, Format, Number). While Number identifies a tag, Class component
+is used to create scopes for Numbers. Four scopes are currently defined:
+UNIVERSAL, context-specific, APPLICATION and PRIVATE. The Format component
+is actually a one-bit flag - zero for tags associated with scalar types,
+and one for constructed types (will be discussed later on).
+</p>
+
+<table bgcolor="lightgray" border=0 width=100%><TR><TD>
+<pre>
+MyIntegerType ::= [12] INTEGER
+MyOctetString ::= [APPLICATION 0] OCTET STRING
+</pre>
+</td></tr></table>
+
+<p>
+In pyasn1, tags are implemented as immutable, tuple-like objects:
+</p>
+
+<table bgcolor="lightgray" border=0 width=100%><TR><TD>
+<pre>
+>>> from pyasn1.type import tag
+>>> myTag = tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10)
+>>> myTag
+Tag(tagClass=128, tagFormat=0, tagId=10)
+>>> tuple(myTag)
+(128, 0, 10)
+>>> myTag[2]
+10
+>>> myTag == tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 10)
+False
+>>>
+</pre>
+</td></tr></table>
+
+<p>
+Default tag, associated with any ASN.1 type, could be extended or replaced
+to make new type distinguishable from its ancestor. The standard provides
+two modes of tag mangling - IMPLICIT and EXPLICIT.
+</p>
+
+<p>
+EXPLICIT mode works by appending new tag to the existing ones thus creating
+an ordered set of tags. This set will be considered as a whole for type
+identification and encoding purposes. Important property of EXPLICIT tagging
+mode is that it preserves base type information in encoding what makes it
+possible to completely recover type information from encoding.
+</p>
+
+<p>
+When tagging in IMPLICIT mode, the outermost existing tag is dropped and
+replaced with a new one.
+</p>
+
+<table bgcolor="lightgray" border=0 width=100%><TR><TD>
+<pre>
+MyIntegerType ::= [12] IMPLICIT INTEGER
+MyOctetString ::= [APPLICATION 0] EXPLICIT OCTET STRING
+</pre>
+</td></tr></table>
+
+<p>
+To model both modes of tagging, a specialized container TagSet object (holding
+zero, one or more Tag objects) is used in pyasn1.
+</p>
+
+<table bgcolor="lightgray" border=0 width=100%><TR><TD>
+<pre>
+>>> from pyasn1.type import tag
+>>> tagSet = tag.TagSet(
+... # base tag
+... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10),
+... # effective tag
+... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10)
+... )
+>>> tagSet
+TagSet(Tag(tagClass=128, tagFormat=0, tagId=10))
+>>> tagSet.getBaseTag()
+Tag(tagClass=128, tagFormat=0, tagId=10)
+>>> tagSet = tagSet.tagExplicitly(
+... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 20)
+... )
+>>> tagSet
+TagSet(Tag(tagClass=128, tagFormat=0, tagId=10),
+ Tag(tagClass=128, tagFormat=32, tagId=20))
+>>> tagSet = tagSet.tagExplicitly(
+... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 30)
+... )
+>>> tagSet
+TagSet(Tag(tagClass=128, tagFormat=0, tagId=10),
+ Tag(tagClass=128, tagFormat=32, tagId=20),
+ Tag(tagClass=128, tagFormat=32, tagId=30))
+>>> tagSet = tagSet.tagImplicitly(
+... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 40)
+... )
+>>> tagSet
+TagSet(Tag(tagClass=128, tagFormat=0, tagId=10),
+ Tag(tagClass=128, tagFormat=32, tagId=20),
+ Tag(tagClass=128, tagFormat=32, tagId=40))
+>>>
+</pre>
+</td></tr></table>
+
+<p>
+As a side note: the "base tag" concept (accessible through the getBaseTag()
+method) is specific to pyasn1 -- the base tag is used to identify the original
+ASN.1 type of an object in question. Base tag is never occurs in encoding
+and is mostly used internally by pyasn1 for choosing type-specific data
+processing algorithms. The "effective tag" is the one that always appears in
+encoding and is used on tagSets comparation.
+</p>
+
+<p>
+Any two TagSet objects could be compared to see if one is a derivative
+of the other. Figuring this out is also useful in cases when a type-specific
+data processing algorithms are to be chosen.
+</p>
+
+<table bgcolor="lightgray" border=0 width=100%><TR><TD>
+<pre>
+>>> from pyasn1.type import tag
+>>> tagSet1 = tag.TagSet(
+... # base tag
+... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10)
+... # effective tag
+... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10)
+... )
+>>> tagSet2 = tagSet1.tagExplicitly(
+... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 20)
+... )
+>>> tagSet1.isSuperTagSetOf(tagSet2)
+True
+>>> tagSet2.isSuperTagSetOf(tagSet1)
+False
+>>>
+</pre>
+</td></tr></table>
+
+<p>
+We will complete this discussion on tagging with a real-world example. The
+following ASN.1 tagged type:
+</p>
+
+<table bgcolor="lightgray" border=0 width=100%><TR><TD>
+<pre>
+MyIntegerType ::= [12] EXPLICIT INTEGER
+</pre>
+</td></tr></table>
+
+<p>
+could be expressed in pyasn1 like this:
+</p>
+
+<table bgcolor="lightgray" border=0 width=100%><TR><TD>
+<pre>
+>>> from pyasn1.type import univ, tag
+>>> class MyIntegerType(univ.Integer):
+... tagSet = univ.Integer.tagSet.tagExplicitly(
+... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 12)
+... )
+>>> myInteger = MyIntegerType(12345)
+>>> myInteger.getTagSet()
+TagSet(Tag(tagClass=0, tagFormat=0, tagId=2),
+ Tag(tagClass=128, tagFormat=32, tagId=12))
+>>>
+</pre>
+</td></tr></table>
+
+<p>
+Referring to the above code, the tagSet class attribute is a property of any
+pyasn1 type object that assigns default tagSet to a pyasn1 value object. This
+default tagSet specification can be ignored and effectively replaced by some
+other tagSet value passed on object instantiation.
+</p>
+
+<p>
+It's important to understand that the tag set property of pyasn1 type/value
+object can never be modifed in place. In other words, a pyasn1 type/value
+object can never change its tags. The only way is to create a new pyasn1
+type/value object and associate different tag set with it.
+</p>
+
+<hr>
+
+</td>
+</tr>
+</table>
+</center>
+</body>
+</html>