mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-09-17 12:55:56 +00:00
234 lines
6.7 KiB
HTML
234 lines
6.7 KiB
HTML
<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>
|