@@ -21,35 +21,70 @@ constructed data types. Primitive data types can be encoded and decoded
2121directly with `read() ` and `write() ` methods. For these types, ASN.1 types are
2222mapped directly to Python types and vice versa, as per the table below:
2323
24- ================ ================= =============
25- ASN.1 type Python type Default
26- ================ ================= =============
27- Boolean bool yes
28- Integer int yes
29- OctetString bytes yes
30- PrintableString str yes
31- Null None yes
32- ObjectIdentifier bytes no
33- Enumerated int no
34- ================ ================= =============
35-
36- The column **default ** is relevant for encoding only. Because
37- ASN.1 has more data types than Python, the situation arises that one Python
38- type corresponds to multiple ASN.1 types. In this sitution the to be encoded
24+ ================ ========== =========== =============
25+ ASN.1 type Tag Number Decoding Encoding
26+ ================ ========== =========== =============
27+ Boolean 0x01 bool bool
28+ Integer 0x02 int int
29+ Null 0x05 None None
30+ ObjectIdentifier 0x06 str
31+ Real 0x09 float float
32+ Enumerated 0x0A int
33+ UTCTime 0x17
34+ GeneralizedTime 0x18
35+ Date 0x1F
36+ TimeOfDay 0x20
37+ DateTime 0x21
38+ Duration 0x22
39+ ================ ========== =========== =============
40+
41+ Because ASN.1 has more data types than Python, the situation arises that one Python
42+ type corresponds to multiple ASN.1 types. In this situation, the to be encoded
3943ASN.1 type cannot be determined from the Python type. The solution
4044implemented in Python-ASN1 is that the most frequently used type will be the
41- implicit default, and if another type is desired than that must be specified
45+ implicit default. This is indicated in the `Encoding ` column.
46+ If another type is desired than that must be specified
4247explicitly through the API.
4348
44- For constructed types, no type mapping is done at all, even for types where
45- such a mapping would be possible such as the ASN.1 type **sequence
46- of ** which could be mapped to a Python list. For such types a stack
47- based approach is used instead. In this approach, the user needs to
48- explicitly enter/leave the constructed type using the
49+ Some ASN.1 types can be either primitive or constructed. They can be encoded
50+ and decoded like primitive types. The following table shows the mapping between
51+ ASN.1 types and Python types.
52+
53+ ================ ========== =========== =============
54+ ASN.1 type Tag Number Decoding Encoding
55+ ================ ========== =========== =============
56+ BitString 0x03 bytes
57+ OctetString 0x04 bytes bytes
58+ UTF8String 0x0C str
59+ NumericString 0x12 str
60+ PrintableString 0x13 str str
61+ T61String 0x14 str
62+ VideotextString 0x15 str
63+ IA5String 0x16 str
64+ GraphicString 0x19 str
65+ VisibleString 0x1A str
66+ GeneralString 0x1B str
67+ UniversalString 0x1C str
68+ CharacterString 0x1D str
69+ UnicodeString 0x1E str
70+ ================ ========== =========== =============
71+
72+ For constructed types, there are two possibilities. The first is to treat them
73+ as a sequence of types. In this case, the encoder and decoder will automatically
74+ map the ASN.1 types to Python types and vice versa.
75+
76+ ================ ========== =========== =============
77+ ASN.1 type Tag Number Decoding Encoding
78+ ================ ========== =========== =============
79+ Sequence 0x10 list list
80+ Set 0x11 list
81+ ================ ========== =========== =============
82+
83+ The second possibility is to treat them as a stack of types. In this approach,
84+ the user needs to explicitly enter/leave the constructed type using the
4985`Encoder.enter() ` and `Encoder.leave() ` methods of the encoder and the
5086`Decoder.enter() ` and `Decoder.leave() ` methods of the decoder.
5187
52-
5388Encoding
5489--------
5590
@@ -61,9 +96,56 @@ If you want to encode data and retrieve its DER-encoded representation, use code
6196
6297 encoder = asn1.Encoder()
6398 encoder.start()
64- encoder.write(' 1.2.3' , asn1.ObjectIdentifier)
99+ encoder.write(' 1.2.3' , asn1.Numbers. ObjectIdentifier)
65100 encoded_bytes = encoder.output()
66101
102+ It is also possible to encode data directly to a file or any stream:
103+
104+ .. code-block :: python
105+
106+ import asn1
107+
108+ with open (' output.der' , ' wb' ) as f:
109+ encoder = asn1.Encoder()
110+ encoder.start(f)
111+ encoder.write(' 1.2.3' , asn1.Numbers.ObjectIdentifier)
112+
113+ You can encode complex data structures such as sequences and sets:
114+
115+ .. code-block :: python
116+
117+ import asn1
118+
119+ with open (' output.der' , ' wb' ) as f:
120+ encoder = asn1.Encoder()
121+ encoder.start(f)
122+ encoder.write([' test1' , ' test2' , [
123+ 1 ,
124+ 0.125 ,
125+ b ' \x01\x02\x03 '
126+ ]])
127+
128+ ASN.1 types are automatically mapped to Python types.
129+ If you want to precisely specify the ASN.1 type, you have to use the `Encoder.enter() ` and `Encoder.leave() ` methods:
130+
131+ .. code-block :: python
132+
133+ import asn1
134+
135+ with open (' output.der' , ' wb' ) as f:
136+ encoder = asn1.Encoder()
137+ encoder.start(f)
138+ encoder.enter(asn1.Numbers.Sequence)
139+ encoder.write(' test1' , asn1.Numbers.PrintableString)
140+ encoder.write(' test2' , asn1.Numbers.PrintableString)
141+ encoder.enter(asn1.Numbers.Sequence)
142+ encoder.write(1 , asn1.Numbers.Integer)
143+ encoder.write(0.125 , asn1.Numbers.Real)
144+ encoder.write(b ' \x01\x02\x03 ' , asn1.Numbers.OctetString)
145+ encoder.leave()
146+ encoder.leave()
147+
148+ This also allows to encode data progressively, without having to keep everything in memory.
67149
68150Decoding
69151--------
@@ -78,54 +160,105 @@ If you want to decode ASN.1 from DER or BER encoded bytes, use code such as:
78160 decoder.start(encoded_bytes)
79161 tag, value = decoder.read()
80162
163+ It is also possible to decode data directly from a file or any stream:
164+
165+ .. code-block :: python
166+
167+ import asn1
168+
169+ with open (' input.der' , ' rb' ) as f:
170+ decoder = asn1.Decoder()
171+ decoder.start(f)
172+ tag, value = decoder.read()
173+
174+ You can decode complex data structures. The decoder will automatically map ASN.1 types to Python types:
175+
176+ .. code-block :: python
177+
178+ import asn1
179+
180+ with open (' example7.der' , ' rb' ) as f:
181+ decoder = asn1.Decoder()
182+ decoder.start(f)
183+ tag, value = decoder.read()
184+ print (tag)
185+ pprint.pprint(value)
81186
82187 Constants
83188---------
84189
85190A few constants are defined in the `asn1 ` module. The
86- constants immediately below correspond to ASN.1 numbers. They can be used as
191+ constants immediately below correspond to ASN.1 tag numbers.
192+ They can be used as
87193the ``nr `` parameter of the
88194`Encoder.write() ` method, and are returned as the
89195first part of a ``(nr, typ, cls) `` tuple as returned by
90196`Decoder.peek() ` and
91197`Decoder.read() `.
92198
93- ================ ===========
94- Constant Value (hex)
95- ================ ===========
96- Boolean 0x01
97- Integer 0x02
98- OctetString 0x04
99- Null 0x05
100- ObjectIdentifier 0x06
101- Enumerated 0x0a
102- Sequence 0x10
103- Set 0x11
104- ================ ===========
199+ ==================================== ===========
200+ Constant Value (hex)
201+ ==================================== ===========
202+ Numbers.Boolean 0x01
203+ Numbers.Integer 0x02
204+ Numbers.BitString 0x03
205+ Numbers.OctetString 0x04
206+ Numbers.Null 0x05
207+ Numbers.ObjectIdentifier 0x06
208+ Numbers.ObjectDescriptor 0x07
209+ Numbers.External 0x08
210+ Numbers.Real 0x09
211+ Numbers.Enumerated 0x0a
212+ Numbers.EmbeddedPDV 0x0b
213+ Numbers.UTF8String 0x0c
214+ Numbers.RelativeOID 0x0d
215+ Numbers.Time 0x0e
216+ Numbers.Sequence 0x10
217+ Numbers.Set 0x11
218+ Numbers.NumericString 0x12
219+ Numbers.PrintableString 0x13
220+ Numbers.T61String 0x14
221+ Numbers.VideotextString 0x15
222+ Numbers.IA5String 0x16
223+ Numbers.UTCTime 0x17
224+ Numbers.GeneralizedTime 0x18
225+ Numbers.GraphicString 0x19
226+ Numbers.VisibleString 0x1a
227+ Numbers.GeneralString 0x1b
228+ Numbers.UniversalString 0x1c
229+ Numbers.CharacterString 0x1d
230+ Numbers.UnicodeString 0x1e
231+ Numbers.Date 0x1f
232+ Numbers.TimeOfDay 0x20
233+ Numbers.DateTime 0x21
234+ Numbers.Duration 0x22
235+ Numbers.OIDinternationalized 0x23
236+ Numbers.RelativeOIDinternationalized 0x24
237+ ==================================== ===========
105238
106239The following constants define the two available encoding types (primitive
107240and constructed) for ASN.1 data types. As above they can be used with the
108241`Encoder.write() ` and are returned by
109242`Decoder.peek() ` and
110243`Decoder.read() `.
111244
112- ================ ===========
113- Constant Value (hex)
114- ================ ===========
115- TypeConstructed 0x20
116- TypePrimitive 0x00
117- ================ ===========
245+ ================== ===========
246+ Constant Value (hex)
247+ ================== = ===========
248+ Types.Constructed 0x20
249+ Types.Primitive 0x00
250+ ================== ===========
118251
119- Finally the constants below define the different ASN.1 classes. As above
252+ Finally the constants below define the different ASN.1 classes. As above
120253they can be used with the `Encoder.write() ` and are
121254returned by `Decoder.peek() ` and
122255`Decoder.read() `.
123256
124- ================ ===========
125- Constant Value (hex)
126- ================ ===========
127- ClassUniversal 0x00
128- ClassApplication 0x40
129- ClassContext 0x80
130- ClassPrivate 0xc0
131- ================ ===========
257+ =================== ===========
258+ Constant Value (hex)
259+ =================== ===========
260+ Classes.Universal 0x00
261+ Classes.Application 0x40
262+ Classes.Context 0x80
263+ Classes.Private 0xc0
264+ =================== ===========
0 commit comments