Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(121)

Side by Side Diff: tools/telemetry/third_party/gsutil/third_party/pyasn1/doc/pyasn1-tutorial.html

Issue 1258583006: Add gsutil 4.13 to telemetry/third_party (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Undo all other changes so this just add gsutil to third_party Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 <html>
2 <title>
3 PyASN1 programmer's manual
4 </title>
5 <head>
6 </head>
7 <body>
8 <center>
9 <table width=60%>
10 <tr>
11 <td>
12
13 <h3>
14 PyASN1 programmer's manual
15 </h3>
16
17 <p align=right>
18 <i>written by <a href=mailto:ilya@glas.net>Ilya Etingof</a>, 2011-2012</i>
19 </p>
20
21 <p>
22 Free and open-source pyasn1 library makes it easier for programmers and
23 network engineers to develop, debug and experiment with ASN.1-based protocols
24 using Python programming language as a tool.
25 </p>
26
27 <p>
28 Abstract Syntax Notation One
29 (<a href=http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_1x>ASN.1</a>)
30 is a set of
31 <a href=http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-X.693-0207w.z ip>
32 ITU standards</a> concered with provisioning instrumentation for developing
33 data exchange protocols in a robust, clear and interoperabable way for
34 various IT systems and applications. Most of the efforts are targeting the
35 following areas:
36 <ul>
37 <li>Data structures: the standard introduces a collection of basic data types
38 (similar to integers, bits, strings, arrays and records in a programming
39 language) that can be used for defining complex, possibly nested data
40 structures representing domain-specific data units.
41 <li>Serialization protocols: domain-specific data units expressed in ASN.1
42 types could be converted into a series of octets for storage or transmission
43 over the wire and then recovered back into their structured form on the
44 receiving end. This process is immune to various hardware and software
45 related dependencies.
46 <li>Data description language: could be used to describe particular set of
47 domain-specific data structures and their relationships. Such a description
48 could be passed to an ASN.1 compiler for automated generation of program
49 code that represents ASN.1 data structures in language-native environment
50 and handles data serialization issues.
51 </ul>
52 </p>
53
54 <p>
55 This tutorial and algorithms, implemented by pyasn1 library, are
56 largely based on the information read in the book
57 <a href="http://www.oss.com/asn1/dubuisson.html">
58 ASN.1 - Communication between heterogeneous systems</a>
59 by Olivier Dubuisson. Another relevant resource is
60 <a href=ftp://ftp.rsasecurity.com/pub/pkcs/ascii/layman.asc>
61 A Layman's Guide to a Subset of ASN.1, BER, and DER</a> by Burton S. Kaliski.
62 It's advised to refer to these books for more in-depth knowledge on the
63 subject of ASN.1.
64 </p>
65
66 <p>
67 As of this writing, pyasn1 library implements most of standard ASN.1 data
68 structures in a rather detailed and feature-rich manner. Another highly
69 important capability of the library is its data serialization facilities.
70 The last component of the standard - ASN.1 compiler is planned for
71 implementation in the future.
72 </p>
73
74 </p>
75 The pyasn1 library was designed to follow the pre-1995 ASN.1 specification
76 (also known as X.208). Later, post 1995, revision (X.680) introduced
77 significant changes most of which have not yet been supported by pyasn1.
78 </p>
79
80 <h3>
81 Table of contents
82 </h3>
83
84 <p>
85 <ul>
86 <li><a href="#1">1. Data model for ASN.1 types</a>
87 <li><a href="#1.1">1.1 Scalar types</a>
88 <li><a href="#1.1.1">1.1.1 Boolean type</a>
89 <li><a href="#1.1.2">1.1.2 Null type</a>
90 <li><a href="#1.1.3">1.1.3 Integer type</a>
91 <li><a href="#1.1.4">1.1.4 Enumerated type</a>
92 <li><a href="#1.1.5">1.1.5 Real type</a>
93 <li><a href="#1.1.6">1.1.6 Bit string type</a>
94 <li><a href="#1.1.7">1.1.7 OctetString type</a>
95 <li><a href="#1.1.8">1.1.8 ObjectIdentifier type</a>
96 <li><a href="#1.1.9">1.1.9 Character string types</a>
97 <li><a href="#1.1.10">1.1.10 Useful types</a>
98 <li><a href="#1.2">1.2 Tagging</a>
99 <li><a href="#1.3">1.3 Constructed types</a>
100 <li><a href="#1.3.1">1.3.1 Sequence and Set types</a>
101 <li><a href="#1.3.2">1.3.2 SequenceOf and SetOf types</a>
102 <li><a href="#1.3.3">1.3.3 Choice type</a>
103 <li><a href="#1.3.4">1.3.4 Any type</a>
104 <li><a href="#1.4">1.4 Subtype constraints</a>
105 <li><a href="#1.4.1">1.4.1 Single value constraint</a>
106 <li><a href="#1.4.2">1.4.2 Value range constraint</a>
107 <li><a href="#1.4.3">1.4.3 Size constraint</a>
108 <li><a href="#1.4.4">1.4.4 Alphabet constraint</a>
109 <li><a href="#1.4.5">1.4.5 Constraint combinations</a>
110 <li><a href="#1.5">1.5 Types relationships</a>
111 <li><a href="#2">2. Codecs</a>
112 <li><a href="#2.1">2.1 Encoders</a>
113 <li><a href="#2.2">2.2 Decoders</a>
114 <li><a href="#2.2.1">2.2.1 Decoding untagged types</a>
115 <li><a href="#2.2.2">2.2.2 Ignoring unknown types</a>
116 <li><a href="#3">3. Feedback and getting help</a>
117 </ul>
118
119
120 <a name="1"></a>
121 <h3>
122 1. Data model for ASN.1 types
123 </h3>
124
125 <p>
126 All ASN.1 types could be categorized into two groups: scalar (also called
127 simple or primitive) and constructed. The first group is populated by
128 well-known types like Integer or String. Members of constructed group
129 hold other types (simple or constructed) as their inner components, thus
130 they are semantically close to a programming language records or lists.
131 </p>
132
133 <p>
134 In pyasn1, all ASN.1 types and values are implemented as Python objects.
135 The same pyasn1 object can represent either ASN.1 type and/or value
136 depending of the presense of value initializer on object instantiation.
137 We will further refer to these as <i>pyasn1 type object</i> versus <i>pyasn1
138 value object</i>.
139 </p>
140
141 <p>
142 Primitive ASN.1 types are implemented as immutable scalar objects. There values
143 could be used just like corresponding native Python values (integers,
144 strings/bytes etc) and freely mixed with them in expressions.
145 </p>
146
147 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
148 <pre>
149 >>> from pyasn1.type import univ
150 >>> asn1IntegerValue = univ.Integer(12)
151 >>> asn1IntegerValue - 2
152 10
153 >>> univ.OctetString('abc') == 'abc'
154 True # Python 2
155 >>> univ.OctetString(b'abc') == b'abc'
156 True # Python 3
157 </pre>
158 </td></tr></table>
159
160 <p>
161 It would be an error to perform an operation on a pyasn1 type object
162 as it holds no value to deal with:
163 </p>
164
165 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
166 <pre>
167 >>> from pyasn1.type import univ
168 >>> asn1IntegerType = univ.Integer()
169 >>> asn1IntegerType - 2
170 ...
171 pyasn1.error.PyAsn1Error: No value for __coerce__()
172 </pre>
173 </td></tr></table>
174
175 <a name="1.1"></a>
176 <h4>
177 1.1 Scalar types
178 </h4>
179
180 <p>
181 In the sub-sections that follow we will explain pyasn1 mapping to those
182 primitive ASN.1 types. Both, ASN.1 notation and corresponding pyasn1
183 syntax will be given in each case.
184 </p>
185
186 <a name="1.1.1"></a>
187 <h4>
188 1.1.1 Boolean type
189 </h4>
190
191 <p>
192 This is the simplest type those values could be either True or False.
193 </p>
194
195 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
196 <pre>
197 ;; type specification
198 FunFactorPresent ::= BOOLEAN
199
200 ;; values declaration and assignment
201 pythonFunFactor FunFactorPresent ::= TRUE
202 cobolFunFactor FunFactorPresent :: FALSE
203 </pre>
204 </td></tr></table>
205
206 <p>
207 And here's pyasn1 version of it:
208 </p>
209
210 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
211 <pre>
212 >>> from pyasn1.type import univ
213 >>> class FunFactorPresent(univ.Boolean): pass
214 ...
215 >>> pythonFunFactor = FunFactorPresent(True)
216 >>> cobolFunFactor = FunFactorPresent(False)
217 >>> pythonFunFactor
218 FunFactorPresent('True(1)')
219 >>> cobolFunFactor
220 FunFactorPresent('False(0)')
221 >>> pythonFunFactor == cobolFunFactor
222 False
223 >>>
224 </pre>
225 </td></tr></table>
226
227 <a name="1.1.2"></a>
228 <h4>
229 1.1.2 Null type
230 </h4>
231
232 <p>
233 The NULL type is sometimes used to express the absense of any information.
234 </p>
235
236 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
237 <pre>
238 ;; type specification
239 Vote ::= CHOICE {
240 agreed BOOLEAN,
241 skip NULL
242 }
243 </td></tr></table>
244
245 ;; value declaration and assignment
246 myVote Vote ::= skip:NULL
247 </pre>
248
249 <p>
250 We will explain the CHOICE type later in this paper, meanwhile the NULL
251 type:
252 </p>
253
254 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
255 <pre>
256 >>> from pyasn1.type import univ
257 >>> skip = univ.Null()
258 >>> skip
259 Null('')
260 >>>
261 </pre>
262 </td></tr></table>
263
264 <a name="1.1.3"></a>
265 <h4>
266 1.1.3 Integer type
267 </h4>
268
269 <p>
270 ASN.1 defines the values of Integer type as negative or positive of whatever
271 length. This definition plays nicely with Python as the latter places no
272 limit on Integers. However, some ASN.1 implementations may impose certain
273 limits of integer value ranges. Keep that in mind when designing new
274 data structures.
275 </p>
276
277 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
278 <pre>
279 ;; values specification
280 age-of-universe INTEGER ::= 13750000000
281 mean-martian-surface-temperature INTEGER ::= -63
282 </pre>
283 </td></tr></table>
284
285 <p>
286 A rather strigntforward mapping into pyasn1:
287 </p>
288
289 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
290 <pre>
291 >>> from pyasn1.type import univ
292 >>> ageOfUniverse = univ.Integer(13750000000)
293 >>> ageOfUniverse
294 Integer(13750000000)
295 >>>
296 >>> meanMartianSurfaceTemperature = univ.Integer(-63)
297 >>> meanMartianSurfaceTemperature
298 Integer(-63)
299 >>>
300 </pre>
301 </td></tr></table>
302
303 <p>
304 ASN.1 allows to assign human-friendly names to particular values of
305 an INTEGER type.
306 </p>
307
308 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
309 <pre>
310 Temperature ::= INTEGER {
311 freezing(0),
312 boiling(100)
313 }
314 </pre>
315 </td></tr></table>
316
317 <p>
318 The Temperature type expressed in pyasn1:
319 </p>
320
321 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
322 <pre>
323 >>> from pyasn1.type import univ, namedval
324 >>> class Temperature(univ.Integer):
325 ... namedValues = namedval.NamedValues(('freezing', 0), ('boiling', 100))
326 ...
327 >>> t = Temperature(0)
328 >>> t
329 Temperature('freezing(0)')
330 >>> t + 1
331 Temperature(1)
332 >>> t + 100
333 Temperature('boiling(100)')
334 >>> t = Temperature('boiling')
335 >>> t
336 Temperature('boiling(100)')
337 >>> Temperature('boiling') / 2
338 Temperature(50)
339 >>> -1 < Temperature('freezing')
340 True
341 >>> 47 > Temperature('boiling')
342 False
343 >>>
344 </pre>
345 </td></tr></table>
346
347 <p>
348 These values labels have no effect on Integer type operations, any value
349 still could be assigned to a type (information on value constraints will
350 follow further in this paper).
351 </p>
352
353 <a name="1.1.4"></a>
354 <h4>
355 1.1.4 Enumerated type
356 </h4>
357
358 <p>
359 ASN.1 Enumerated type differs from an Integer type in a number of ways.
360 Most important is that its instance can only hold a value that belongs
361 to a set of values specified on type declaration.
362 </p>
363
364 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
365 <pre>
366 error-status ::= ENUMERATED {
367 no-error(0),
368 authentication-error(10),
369 authorization-error(20),
370 general-failure(51)
371 }
372 </pre>
373 </td></tr></table>
374
375 <p>
376 When constructing Enumerated type we will use two pyasn1 features: values
377 labels (as mentioned above) and value constraint (will be described in
378 more details later on).
379 </p>
380
381 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
382 <pre>
383 >>> from pyasn1.type import univ, namedval, constraint
384 >>> class ErrorStatus(univ.Enumerated):
385 ... namedValues = namedval.NamedValues(
386 ... ('no-error', 0),
387 ... ('authentication-error', 10),
388 ... ('authorization-error', 20),
389 ... ('general-failure', 51)
390 ... )
391 ... subtypeSpec = univ.Enumerated.subtypeSpec + \
392 ... constraint.SingleValueConstraint(0, 10, 20, 51)
393 ...
394 >>> errorStatus = univ.ErrorStatus('no-error')
395 >>> errorStatus
396 ErrorStatus('no-error(0)')
397 >>> errorStatus == univ.ErrorStatus('general-failure')
398 False
399 >>> univ.ErrorStatus('non-existing-state')
400 Traceback (most recent call last):
401 ...
402 pyasn1.error.PyAsn1Error: Can't coerce non-existing-state into integer
403 >>>
404 </pre>
405 </td></tr></table>
406
407 <p>
408 Particular integer values associated with Enumerated value states
409 have no meaning. They should not be used as such or in any kind of
410 math operation. Those integer values are only used by codecs to
411 transfer state from one entity to another.
412 </p>
413
414 <a name="1.1.5"></a>
415 <h4>
416 1.1.5 Real type
417 </h4>
418
419 <p>
420 Values of the Real type are a three-component tuple of mantissa, base and
421 exponent. All three are integers.
422 </p>
423
424 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
425 <pre>
426 pi ::= REAL { mantissa 314159, base 10, exponent -5 }
427 </pre>
428 </td></tr></table>
429
430 <p>
431 Corresponding pyasn1 objects can be initialized with either a three-component
432 tuple or a Python float. Infinite values could be expressed in a way,
433 compatible with Python float type.
434
435 </p>
436
437 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
438 <pre>
439 >>> from pyasn1.type import univ
440 >>> pi = univ.Real((314159, 10, -5))
441 >>> pi
442 Real((314159, 10,-5))
443 >>> float(pi)
444 3.14159
445 >>> pi == univ.Real(3.14159)
446 True
447 >>> univ.Real('inf')
448 Real('inf')
449 >>> univ.Real('-inf') == float('-inf')
450 True
451 >>>
452 </pre>
453 </td></tr></table>
454
455 <p>
456 If a Real object is initialized from a Python float or yielded by a math
457 operation, the base is set to decimal 10 (what affects encoding).
458 </p>
459
460 <a name="1.1.6"></a>
461 <h4>
462 1.1.6 Bit string type
463 </h4>
464
465 <p>
466 ASN.1 BIT STRING type holds opaque binary data of an arbitrarily length.
467 A BIT STRING value could be initialized by either a binary (base 2) or
468 hex (base 16) value.
469 </p>
470
471 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
472 <pre>
473 public-key BIT STRING ::= '1010111011110001010110101101101
474 1011000101010000010110101100010
475 0110101010000111101010111111110'B
476
477 signature BIT STRING ::= 'AF01330CD932093392100B39FF00DE0'H
478 </pre>
479 </td></tr></table>
480
481 <p>
482 The pyasn1 BitString objects can initialize from native ASN.1 notation
483 (base 2 or base 16 strings) or from a Python tuple of binary components.
484 </p>
485
486 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
487 <pre>
488 >>> from pyasn1.type import univ
489 >>> publicKey = univ.BitString(
490 ... "'1010111011110001010110101101101"
491 ... "1011000101010000010110101100010"
492 ... "0110101010000111101010111111110'B"
493 )
494 >>> publicKey
495 BitString("'10101110111100010101101011011011011000101010000010110101100010\
496 0110101010000111101010111111110'B")
497 >>> signature = univ.BitString(
498 ... "'AF01330CD932093392100B39FF00DE0'H"
499 ... )
500 >>> signature
501 BitString("'101011110000000100110011000011001101100100110010000010010011001\
502 1100100100001000000001011001110011111111100000000110111100000'B")
503 >>> fingerprint = univ.BitString(
504 ... (1, 0, 1, 1 ,0, 1, 1, 1, 0, 1, 0, 1)
505 ... )
506 >>> fingerprint
507 BitString("'101101110101'B")
508 >>>
509 </pre>
510 </td></tr></table>
511
512 <p>
513 Another BIT STRING initialization method supported by ASN.1 notation
514 is to specify only 1-th bits along with their human-friendly label
515 and bit offset relative to the beginning of the bit string. With this
516 method, all not explicitly mentioned bits are doomed to be zeros.
517 </p>
518
519 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
520 <pre>
521 bit-mask BIT STRING ::= {
522 read-flag(0),
523 write-flag(2),
524 run-flag(4)
525 }
526 </pre>
527 </td></tr></table>
528
529 <p>
530 To express this in pyasn1, we will employ the named values feature (as with
531 Enumeration type).
532 </p>
533
534 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
535 <pre>
536 >>> from pyasn1.type import univ, namedval
537 >>> class BitMask(univ.BitString):
538 ... namedValues = namedval.NamedValues(
539 ... ('read-flag', 0),
540 ... ('write-flag', 2),
541 ... ('run-flag', 4)
542 ... )
543 >>> bitMask = BitMask('read-flag,run-flag')
544 >>> bitMask
545 BitMask("'10001'B")
546 >>> tuple(bitMask)
547 (1, 0, 0, 0, 1)
548 >>> bitMask[4]
549 1
550 >>>
551 </pre>
552 </td></tr></table>
553
554 <p>
555 The BitString objects mimic the properties of Python tuple type in part
556 of immutable sequence object protocol support.
557 </p>
558
559 <a name="1.1.7"></a>
560 <h4>
561 1.1.7 OctetString type
562 </h4>
563
564 <p>
565 The OCTET STRING type is a confusing subject. According to ASN.1
566 specification, this type is similar to BIT STRING, the major difference
567 is that the former operates in 8-bit chunks of data. What is important
568 to note, is that OCTET STRING was NOT designed to handle text strings - the
569 standard provides many other types specialized for text content. For that
570 reason, ASN.1 forbids to initialize OCTET STRING values with "quoted text
571 strings", only binary or hex initializers, similar to BIT STRING ones,
572 are allowed.
573 </p>
574
575 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
576 <pre>
577 thumbnail OCTET STRING ::= '1000010111101110101111000000111011'B
578 thumbnail OCTET STRING ::= 'FA9823C43E43510DE3422'H
579 </pre>
580 </td></tr></table>
581
582 <p>
583 However, ASN.1 users (e.g. protocols designers) seem to ignore the original
584 purpose of the OCTET STRING type - they used it for handling all kinds of
585 data, including text strings.
586 </p>
587
588 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
589 <pre>
590 welcome-message OCTET STRING ::= "Welcome to ASN.1 wilderness!"
591 </pre>
592 </td></tr></table>
593
594 <p>
595 In pyasn1, we have taken a liberal approach and allowed both BIT STRING
596 style and quoted text initializers for the OctetString objects. To avoid
597 possible collisions, quoted text is the default initialization syntax.
598 </p>
599
600 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
601 <pre>
602 >>> from pyasn1.type import univ
603 >>> thumbnail = univ.OctetString(
604 ... binValue='1000010111101110101111000000111011'
605 ... )
606 >>> thumbnail
607 OctetString(hexValue='85eebcec0')
608 >>> thumbnail = univ.OctetString(
609 ... hexValue='FA9823C43E43510DE3422'
610 ... )
611 >>> thumbnail
612 OctetString(hexValue='fa9823c43e4351de34220')
613 >>>
614 </pre>
615 </td></tr></table>
616
617 <p>
618 Most frequent usage of the OctetString class is to instantiate it with
619 a text string.
620 </p>
621
622 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
623 <pre>
624 >>> from pyasn1.type import univ
625 >>> welcomeMessage = univ.OctetString('Welcome to ASN.1 wilderness!')
626 >>> welcomeMessage
627 OctetString(b'Welcome to ASN.1 wilderness!')
628 >>> print('%s' % welcomeMessage)
629 Welcome to ASN.1 wilderness!
630 >>> welcomeMessage[11:16]
631 OctetString(b'ASN.1')
632 >>>
633 </pre>
634 </td></tr></table>
635
636 <p>
637 OctetString objects support the immutable sequence object protocol.
638 In other words, they behave like Python 3 bytes (or Python 2 strings).
639 </p>
640
641 <p>
642 When running pyasn1 on Python 3, it's better to use the bytes objects for
643 OctetString instantiation, as it's more reliable and efficient.
644 </p>
645
646 <p>
647 Additionally, OctetString's can also be instantiated with a sequence of
648 8-bit integers (ASCII codes).
649 </p>
650
651 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
652 <pre>
653 >>> univ.OctetString((77, 101, 101, 103, 111))
654 OctetString(b'Meego')
655 </pre>
656 </td></tr></table>
657
658 <p>
659 It is sometimes convenient to express OctetString instances as 8-bit
660 characters (Python 3 bytes or Python 2 strings) or 8-bit integers.
661 </p>
662
663 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
664 <pre>
665 >>> octetString = univ.OctetString('ABCDEF')
666 >>> octetString.asNumbers()
667 (65, 66, 67, 68, 69, 70)
668 >>> octetString.asOctets()
669 b'ABCDEF'
670 </pre>
671 </td></tr></table>
672
673 <a name="1.1.8"></a>
674 <h4>
675 1.1.8 ObjectIdentifier type
676 </h4>
677
678 <p>
679 Values of the OBJECT IDENTIFIER type are sequences of integers that could
680 be used to identify virtually anything in the world. Various ASN.1-based
681 protocols employ OBJECT IDENTIFIERs for their own identification needs.
682 </p>
683
684 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
685 <pre>
686 internet-id OBJECT IDENTIFIER ::= {
687 iso(1) identified-organization(3) dod(6) internet(1)
688 }
689 </pre>
690 </td></tr></table>
691
692 <p>
693 One of the natural ways to map OBJECT IDENTIFIER type into a Python
694 one is to use Python tuples of integers. So this approach is taken by
695 pyasn1.
696 </p>
697
698 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
699 <pre>
700 >>> from pyasn1.type import univ
701 >>> internetId = univ.ObjectIdentifier((1, 3, 6, 1))
702 >>> internetId
703 ObjectIdentifier('1.3.6.1')
704 >>> internetId[2]
705 6
706 >>> internetId[1:3]
707 ObjectIdentifier('3.6')
708 </pre>
709 </td></tr></table>
710
711 <p>
712 A more human-friendly "dotted" notation is also supported.
713 </p>
714
715 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
716 <pre>
717 >>> from pyasn1.type import univ
718 >>> univ.ObjectIdentifier('1.3.6.1')
719 ObjectIdentifier('1.3.6.1')
720 </pre>
721 </td></tr></table>
722
723 <p>
724 Symbolic names of the arcs of object identifier, sometimes present in
725 ASN.1 specifications, are not preserved and used in pyasn1 objects.
726 </p>
727
728 <p>
729 The ObjectIdentifier objects mimic the properties of Python tuple type in
730 part of immutable sequence object protocol support.
731 </p>
732
733 <a name="1.1.9"></a>
734 <h4>
735 1.1.9 Character string types
736 </h4>
737
738 <p>
739 ASN.1 standard introduces a diverse set of text-specific types. All of them
740 were designed to handle various types of characters. Some of these types seem
741 be obsolete nowdays, as their target technologies are gone. Another issue
742 to be aware of is that raw OCTET STRING type is sometimes used in practice
743 by ASN.1 users instead of specialized character string types, despite
744 explicit prohibition imposed by ASN.1 specification.
745 </p>
746
747 <p>
748 The two types are specific to ASN.1 are NumericString and PrintableString.
749 </p>
750
751 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
752 <pre>
753 welcome-message ::= PrintableString {
754 "Welcome to ASN.1 text types"
755 }
756
757 dial-pad-numbers ::= NumericString {
758 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
759 }
760 </pre>
761 </td></tr></table>
762
763 <p>
764 Their pyasn1 implementations are:
765 </p>
766
767 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
768 <pre>
769 >>> from pyasn1.type import char
770 >>> '%s' % char.PrintableString("Welcome to ASN.1 text types")
771 'Welcome to ASN.1 text types'
772 >>> dialPadNumbers = char.NumericString(
773 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"
774 )
775 >>> dialPadNumbers
776 NumericString(b'0123456789')
777 >>>
778 </pre>
779 </td></tr></table>
780
781 <p>
782 The following types came to ASN.1 from ISO standards on character sets.
783 </p>
784
785 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
786 <pre>
787 >>> from pyasn1.type import char
788 >>> char.VisibleString("abc")
789 VisibleString(b'abc')
790 >>> char.IA5String('abc')
791 IA5String(b'abc')
792 >>> char.TeletexString('abc')
793 TeletexString(b'abc')
794 >>> char.VideotexString('abc')
795 VideotexString(b'abc')
796 >>> char.GraphicString('abc')
797 GraphicString(b'abc')
798 >>> char.GeneralString('abc')
799 GeneralString(b'abc')
800 >>>
801 </pre>
802 </td></tr></table>
803
804 <p>
805 The last three types are relatively recent addition to the family of
806 character string types: UniversalString, BMPString, UTF8String.
807 </p>
808
809 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
810 <pre>
811 >>> from pyasn1.type import char
812 >>> char.UniversalString("abc")
813 UniversalString(b'abc')
814 >>> char.BMPString('abc')
815 BMPString(b'abc')
816 >>> char.UTF8String('abc')
817 UTF8String(b'abc')
818 >>> utf8String = char.UTF8String('У попа была собака')
819 >>> utf8String
820 UTF8String(b'\xd0\xa3 \xd0\xbf\xd0\xbe\xd0\xbf\xd0\xb0 \xd0\xb1\xd1\x8b\xd0\xbb\ xd0\xb0 \
821 \xd1\x81\xd0\xbe\xd0\xb1\xd0\xb0\xd0\xba\xd0\xb0')
822 >>> print(utf8String)
823 У попа была собака
824 >>>
825 </pre>
826 </td></tr></table>
827
828 <p>
829 In pyasn1, all character type objects behave like Python strings. None of
830 them is currently constrained in terms of valid alphabet so it's up to
831 the data source to keep an eye on data validation for these types.
832 </p>
833
834 <a name="1.1.10"></a>
835 <h4>
836 1.1.10 Useful types
837 </h4>
838
839 <p>
840 There are three so-called useful types defined in the standard:
841 ObjectDescriptor, GeneralizedTime, UTCTime. They all are subtypes
842 of GraphicString or VisibleString types therefore useful types are
843 character string types.
844 </p>
845
846 <p>
847 It's advised by the ASN.1 standard to have an instance of ObjectDescriptor
848 type holding a human-readable description of corresponding instance of
849 OBJECT IDENTIFIER type. There are no formal linkage between these instances
850 and provision for ObjectDescriptor uniqueness in the standard.
851 </p>
852
853 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
854 <pre>
855 >>> from pyasn1.type import useful
856 >>> descrBER = useful.ObjectDescriptor(
857 "Basic encoding of a single ASN.1 type"
858 )
859 >>>
860 </pre>
861 </td></tr></table>
862
863 <p>
864 GeneralizedTime and UTCTime types are designed to hold a human-readable
865 timestamp in a universal and unambiguous form. The former provides
866 more flexibility in notation while the latter is more strict but has
867 Y2K issues.
868 </p>
869
870 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
871 <pre>
872 ;; Mar 8 2010 12:00:00 MSK
873 moscow-time GeneralizedTime ::= "20110308120000.0"
874 ;; Mar 8 2010 12:00:00 UTC
875 utc-time GeneralizedTime ::= "201103081200Z"
876 ;; Mar 8 1999 12:00:00 UTC
877 utc-time UTCTime ::= "9803081200Z"
878 </pre>
879 </td></tr></table>
880
881 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
882 <pre>
883 >>> from pyasn1.type import useful
884 >>> moscowTime = useful.GeneralizedTime("20110308120000.0")
885 >>> utcTime = useful.UTCTime("9803081200Z")
886 >>>
887 </pre>
888 </td></tr></table>
889
890 <p>
891 Despite their intended use, these types possess no special, time-related,
892 handling in pyasn1. They are just printable strings.
893 </p>
894
895 <a name="1.2"></a>
896 <h4>
897 1.2 Tagging
898 </h4>
899
900 <p>
901 In order to continue with the Constructed ASN.1 types, we will first have
902 to introduce the concept of tagging (and its pyasn1 implementation), as
903 some of the Constructed types rely upon the tagging feature.
904 </p>
905
906 <p>
907 When a value is coming into an ASN.1-based system (received from a network
908 or read from some storage), the receiving entity has to determine the
909 type of the value to interpret and verify it accordingly.
910 </p>
911
912 <p>
913 Historically, the first data serialization protocol introduced in
914 ASN.1 was BER (Basic Encoding Rules). According to BER, any serialized
915 value is packed into a triplet of (Type, Length, Value) where Type is a
916 code that identifies the value (which is called <i>tag</i> in ASN.1),
917 length is the number of bytes occupied by the value in its serialized form
918 and value is ASN.1 value in a form suitable for serial transmission or storage.
919 </p>
920
921 <p>
922 For that reason almost every ASN.1 type has a tag (which is actually a
923 BER type) associated with it by default.
924 </p>
925
926 <p>
927 An ASN.1 tag could be viewed as a tuple of three numbers:
928 (Class, Format, Number). While Number identifies a tag, Class component
929 is used to create scopes for Numbers. Four scopes are currently defined:
930 UNIVERSAL, context-specific, APPLICATION and PRIVATE. The Format component
931 is actually a one-bit flag - zero for tags associated with scalar types,
932 and one for constructed types (will be discussed later on).
933 </p>
934
935 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
936 <pre>
937 MyIntegerType ::= [12] INTEGER
938 MyOctetString ::= [APPLICATION 0] OCTET STRING
939 </pre>
940 </td></tr></table>
941
942 <p>
943 In pyasn1, tags are implemented as immutable, tuple-like objects:
944 </p>
945
946 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
947 <pre>
948 >>> from pyasn1.type import tag
949 >>> myTag = tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10)
950 >>> myTag
951 Tag(tagClass=128, tagFormat=0, tagId=10)
952 >>> tuple(myTag)
953 (128, 0, 10)
954 >>> myTag[2]
955 10
956 >>> myTag == tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 10)
957 False
958 >>>
959 </pre>
960 </td></tr></table>
961
962 <p>
963 Default tag, associated with any ASN.1 type, could be extended or replaced
964 to make new type distinguishable from its ancestor. The standard provides
965 two modes of tag mangling - IMPLICIT and EXPLICIT.
966 </p>
967
968 <p>
969 EXPLICIT mode works by appending new tag to the existing ones thus creating
970 an ordered set of tags. This set will be considered as a whole for type
971 identification and encoding purposes. Important property of EXPLICIT tagging
972 mode is that it preserves base type information in encoding what makes it
973 possible to completely recover type information from encoding.
974 </p>
975
976 <p>
977 When tagging in IMPLICIT mode, the outermost existing tag is dropped and
978 replaced with a new one.
979 </p>
980
981 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
982 <pre>
983 MyIntegerType ::= [12] IMPLICIT INTEGER
984 MyOctetString ::= [APPLICATION 0] EXPLICIT OCTET STRING
985 </pre>
986 </td></tr></table>
987
988 <p>
989 To model both modes of tagging, a specialized container TagSet object (holding
990 zero, one or more Tag objects) is used in pyasn1.
991 </p>
992
993 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
994 <pre>
995 >>> from pyasn1.type import tag
996 >>> tagSet = tag.TagSet(
997 ... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10), # base tag
998 ... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10) # effective tag
999 ... )
1000 >>> tagSet
1001 TagSet(Tag(tagClass=128, tagFormat=0, tagId=10))
1002 >>> tagSet.getBaseTag()
1003 Tag(tagClass=128, tagFormat=0, tagId=10)
1004 >>> tagSet = tagSet.tagExplicitly(
1005 ... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 20)
1006 ... )
1007 >>> tagSet
1008 TagSet(Tag(tagClass=128, tagFormat=0, tagId=10),
1009 Tag(tagClass=128, tagFormat=32, tagId=20))
1010 >>> tagSet = tagSet.tagExplicitly(
1011 ... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 30)
1012 ... )
1013 >>> tagSet
1014 TagSet(Tag(tagClass=128, tagFormat=0, tagId=10),
1015 Tag(tagClass=128, tagFormat=32, tagId=20),
1016 Tag(tagClass=128, tagFormat=32, tagId=30))
1017 >>> tagSet = tagSet.tagImplicitly(
1018 ... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 40)
1019 ... )
1020 >>> tagSet
1021 TagSet(Tag(tagClass=128, tagFormat=0, tagId=10),
1022 Tag(tagClass=128, tagFormat=32, tagId=20),
1023 Tag(tagClass=128, tagFormat=32, tagId=40))
1024 >>>
1025 </pre>
1026 </td></tr></table>
1027
1028 <p>
1029 As a side note: the "base tag" concept (accessible through the getBaseTag()
1030 method) is specific to pyasn1 -- the base tag is used to identify the original
1031 ASN.1 type of an object in question. Base tag is never occurs in encoding
1032 and is mostly used internally by pyasn1 for choosing type-specific data
1033 processing algorithms. The "effective tag" is the one that always appears in
1034 encoding and is used on tagSets comparation.
1035 </p>
1036
1037 <p>
1038 Any two TagSet objects could be compared to see if one is a derivative
1039 of the other. Figuring this out is also useful in cases when a type-specific
1040 data processing algorithms are to be chosen.
1041 </p>
1042
1043 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1044 <pre>
1045 >>> from pyasn1.type import tag
1046 >>> tagSet1 = tag.TagSet(
1047 ... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10) # base tag
1048 ... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10) # effective tag
1049 ... )
1050 >>> tagSet2 = tagSet1.tagExplicitly(
1051 ... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 20)
1052 ... )
1053 >>> tagSet1.isSuperTagSetOf(tagSet2)
1054 True
1055 >>> tagSet2.isSuperTagSetOf(tagSet1)
1056 False
1057 >>>
1058 </pre>
1059 </td></tr></table>
1060
1061 <p>
1062 We will complete this discussion on tagging with a real-world example. The
1063 following ASN.1 tagged type:
1064 </p>
1065
1066 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1067 <pre>
1068 MyIntegerType ::= [12] EXPLICIT INTEGER
1069 </pre>
1070 </td></tr></table>
1071
1072 <p>
1073 could be expressed in pyasn1 like this:
1074 </p>
1075
1076 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1077 <pre>
1078 >>> from pyasn1.type import univ, tag
1079 >>> class MyIntegerType(univ.Integer):
1080 ... tagSet = univ.Integer.tagSet.tagExplicitly(
1081 ... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 12)
1082 ... )
1083 >>> myInteger = MyIntegerType(12345)
1084 >>> myInteger.getTagSet()
1085 TagSet(Tag(tagClass=0, tagFormat=0, tagId=2),
1086 Tag(tagClass=128, tagFormat=32, tagId=12))
1087 >>>
1088 </pre>
1089 </td></tr></table>
1090
1091 <p>
1092 Referring to the above code, the tagSet class attribute is a property of any
1093 pyasn1 type object that assigns default tagSet to a pyasn1 value object. This
1094 default tagSet specification can be ignored and effectively replaced by some
1095 other tagSet value passed on object instantiation.
1096 </p>
1097
1098 <p>
1099 It's important to understand that the tag set property of pyasn1 type/value
1100 object can never be modifed in place. In other words, a pyasn1 type/value
1101 object can never change its tags. The only way is to create a new pyasn1
1102 type/value object and associate different tag set with it.
1103 </p>
1104
1105
1106 <a name="1.3"></a>
1107 <h4>
1108 1.3 Constructed types
1109 </h4>
1110
1111 <p>
1112 Besides scalar types, ASN.1 specifies so-called constructed ones - these
1113 are capable of holding one or more values of other types, both scalar
1114 and constructed.
1115 </p>
1116
1117 <p>
1118 In pyasn1 implementation, constructed ASN.1 types behave like
1119 Python sequences, and also support additional component addressing methods,
1120 specific to particular constructed type.
1121 </p>
1122
1123 <a name="1.3.1"></a>
1124 <h4>
1125 1.3.1 Sequence and Set types
1126 </h4>
1127
1128 <p>
1129 The Sequence and Set types have many similar properties:
1130 </p>
1131 <ul>
1132 <li>they can hold any number of inner components of different types
1133 <li>every component has a human-friendly identifier
1134 <li>any component can have a default value
1135 <li>some components can be absent.
1136 </ul>
1137
1138 <p>
1139 However, Sequence type guarantees the ordering of Sequence value components
1140 to match their declaration order. By contrast, components of the
1141 Set type can be ordered to best suite application's needs.
1142 <p>
1143
1144 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1145 <pre>
1146 Record ::= SEQUENCE {
1147 id INTEGER,
1148 room [0] INTEGER OPTIONAL,
1149 house [1] INTEGER DEFAULT 0
1150 }
1151 </pre>
1152 </td></tr></table>
1153
1154 <p>
1155 Up to this moment, the only method we used for creating new pyasn1 types
1156 is Python sub-classing. With this method, a new, named Python class is created
1157 what mimics type derivation in ASN.1 grammar. However, ASN.1 also allows for
1158 defining anonymous subtypes (room and house components in the example above).
1159 To support anonymous subtyping in pyasn1, a cloning operation on an existing
1160 pyasn1 type object can be invoked what creates a new instance of original
1161 object with possibly modified properties.
1162 </p>
1163
1164 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1165 <pre>
1166 >>> from pyasn1.type import univ, namedtype, tag
1167 >>> class Record(univ.Sequence):
1168 ... componentType = namedtype.NamedTypes(
1169 ... namedtype.NamedType('id', univ.Integer()),
1170 ... namedtype.OptionalNamedType(
1171 ... 'room',
1172 ... univ.Integer().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.ta gFormatSimple, 0))
1173 ... ),
1174 ... namedtype.DefaultedNamedType(
1175 ... 'house',
1176 ... univ.Integer(0).subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.t agFormatSimple, 1))
1177 ... )
1178 ... )
1179 >>>
1180 </pre>
1181 </td></tr></table>
1182
1183 <p>
1184 All pyasn1 constructed type classes have a class attribute <b>componentType</b>
1185 that represent default type specification. Its value is a NamedTypes object.
1186 </p>
1187
1188 <p>
1189 The NamedTypes class instance holds a sequence of NameType, OptionalNamedType
1190 or DefaultedNamedType objects which, in turn, refer to pyasn1 type objects that
1191 represent inner SEQUENCE components specification.
1192 </p>
1193
1194 <p>
1195 Finally, invocation of a subtype() method of pyasn1 type objects in the code
1196 above returns an implicitly tagged copy of original object.
1197 </p>
1198
1199 <p>
1200 Once a SEQUENCE or SET type is decleared with pyasn1, it can be instantiated
1201 and initialized (continuing the above code):
1202 </p>
1203
1204 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1205 <pre>
1206 >>> record = Record()
1207 >>> record.setComponentByName('id', 123)
1208 >>> print(record.prettyPrint())
1209 Record:
1210 id=123
1211 >>>
1212 >>> record.setComponentByPosition(1, 321)
1213 >>> print(record.prettyPrint())
1214 Record:
1215 id=123
1216 room=321
1217 >>>
1218 >>> record.setDefaultComponents()
1219 >>> print(record.prettyPrint())
1220 Record:
1221 id=123
1222 room=321
1223 house=0
1224 </pre>
1225 </td></tr></table>
1226
1227 <p>
1228 Inner components of pyasn1 Sequence/Set objects could be accessed using the
1229 following methods:
1230 </p>
1231
1232 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1233 <pre>
1234 >>> record.getComponentByName('id')
1235 Integer(123)
1236 >>> record.getComponentByPosition(1)
1237 Integer(321)
1238 >>> record[2]
1239 Integer(0)
1240 >>> for idx in range(len(record)):
1241 ... print(record.getNameByPosition(idx), record.getComponentByPosition(idx))
1242 id 123
1243 room 321
1244 house 0
1245 >>>
1246 </pre>
1247 </td></tr></table>
1248
1249 <p>
1250 The Set type share all the properties of Sequence type, and additionally
1251 support by-tag component addressing (as all Set components have distinct
1252 types).
1253 </p>
1254
1255 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1256 <pre>
1257 >>> from pyasn1.type import univ, namedtype, tag
1258 >>> class Gamer(univ.Set):
1259 ... componentType = namedtype.NamedTypes(
1260 ... namedtype.NamedType('score', univ.Integer()),
1261 ... namedtype.NamedType('player', univ.OctetString()),
1262 ... namedtype.NamedType('id', univ.ObjectIdentifier())
1263 ... )
1264 >>> gamer = Gamer()
1265 >>> gamer.setComponentByType(univ.Integer().getTagSet(), 121343)
1266 >>> gamer.setComponentByType(univ.OctetString().getTagSet(), 'Pascal')
1267 >>> gamer.setComponentByType(univ.ObjectIdentifier().getTagSet(), (1,3,7,2))
1268 >>> print(gamer.prettyPrint())
1269 Gamer:
1270 score=121343
1271 player=b'Pascal'
1272 id=1.3.7.2
1273 >>>
1274 </pre>
1275 </td></tr></table>
1276
1277 <a name="1.3.2"></a>
1278 <h4>
1279 1.3.2 SequenceOf and SetOf types
1280 </h4>
1281
1282 <p>
1283 Both, SequenceOf and SetOf types resemble an unlimited size list of components.
1284 All the components must be of the same type.
1285 </p>
1286
1287 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1288 <pre>
1289 Progression ::= SEQUENCE OF INTEGER
1290
1291 arithmeticProgression Progression ::= { 1, 3, 5, 7 }
1292 </pre>
1293 </td></tr></table>
1294
1295 <p>
1296 SequenceOf and SetOf types are expressed by the very similar pyasn1 type
1297 objects. Their components can only be addressed by position and they
1298 both have a property of automatic resize.
1299 </p>
1300
1301 <p>
1302 To specify inner component type, the <b>componentType</b> class attribute
1303 should refer to another pyasn1 type object.
1304 </p>
1305
1306 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1307 <pre>
1308 >>> from pyasn1.type import univ
1309 >>> class Progression(univ.SequenceOf):
1310 ... componentType = univ.Integer()
1311 >>> arithmeticProgression = Progression()
1312 >>> arithmeticProgression.setComponentByPosition(1, 111)
1313 >>> print(arithmeticProgression.prettyPrint())
1314 Progression:
1315 -empty- 111
1316 >>> arithmeticProgression.setComponentByPosition(0, 100)
1317 >>> print(arithmeticProgression.prettyPrint())
1318 Progression:
1319 100 111
1320 >>>
1321 >>> for idx in range(len(arithmeticProgression)):
1322 ... arithmeticProgression.getComponentByPosition(idx)
1323 Integer(100)
1324 Integer(111)
1325 >>>
1326 </pre>
1327 </td></tr></table>
1328
1329 <p>
1330 Any scalar or constructed pyasn1 type object can serve as an inner component.
1331 Missing components are prohibited in SequenceOf/SetOf value objects.
1332 </p>
1333
1334 <a name="1.3.3"></a>
1335 <h4>
1336 1.3.3 Choice type
1337 </h4>
1338
1339 <p>
1340 Values of ASN.1 CHOICE type can contain only a single value of a type from a
1341 list of possible alternatives. Alternatives must be ASN.1 types with
1342 distinct tags for the whole structure to remain unambiguous. Unlike most
1343 other types, CHOICE is an untagged one, e.g. it has no base tag of its own.
1344 </p>
1345
1346 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1347 <pre>
1348 CodeOrMessage ::= CHOICE {
1349 code INTEGER,
1350 message OCTET STRING
1351 }
1352 </pre>
1353 </td></tr></table>
1354
1355 <p>
1356 In pyasn1 implementation, Choice object behaves like Set but accepts only
1357 a single inner component at a time. It also offers a few additional methods
1358 specific to its behaviour.
1359 </p>
1360
1361 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1362 <pre>
1363 >>> from pyasn1.type import univ, namedtype
1364 >>> class CodeOrMessage(univ.Choice):
1365 ... componentType = namedtype.NamedTypes(
1366 ... namedtype.NamedType('code', univ.Integer()),
1367 ... namedtype.NamedType('message', univ.OctetString())
1368 ... )
1369 >>>
1370 >>> codeOrMessage = CodeOrMessage()
1371 >>> print(codeOrMessage.prettyPrint())
1372 CodeOrMessage:
1373 >>> codeOrMessage.setComponentByName('code', 123)
1374 >>> print(codeOrMessage.prettyPrint())
1375 CodeOrMessage:
1376 code=123
1377 >>> codeOrMessage.setComponentByName('message', 'my string value')
1378 >>> print(codeOrMessage.prettyPrint())
1379 CodeOrMessage:
1380 message=b'my string value'
1381 >>>
1382 </pre>
1383 </td></tr></table>
1384
1385 <p>
1386 Since there could be only a single inner component value in the pyasn1 Choice
1387 value object, either of the following methods could be used for fetching it
1388 (continuing previous code):
1389 </p>
1390
1391 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1392 <pre>
1393 >>> codeOrMessage.getName()
1394 'message'
1395 >>> codeOrMessage.getComponent()
1396 OctetString(b'my string value')
1397 >>>
1398 </pre>
1399 </td></tr></table>
1400
1401 <a name="1.3.4"></a>
1402 <h4>
1403 1.3.4 Any type
1404 </h4>
1405
1406 <p>
1407 The ASN.1 ANY type is a kind of wildcard or placeholder that matches
1408 any other type without knowing it in advance. Like CHOICE type, ANY
1409 has no base tag.
1410 </p>
1411
1412 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1413 <pre>
1414 Error ::= SEQUENCE {
1415 code INTEGER,
1416 parameter ANY DEFINED BY code
1417 }
1418 </pre>
1419 </td></tr></table>
1420
1421 <p>
1422 The ANY type is frequently used in specifications, where exact type is not
1423 yet agreed upon between communicating parties or the number of possible
1424 alternatives of a type is infinite.
1425 Sometimes an auxiliary selector is kept around to help parties indicate
1426 the kind of ANY payload in effect ("code" in the example above).
1427 </p>
1428
1429 <p>
1430 Values of the ANY type contain serialized ASN.1 value(s) in form of
1431 an octet string. Therefore pyasn1 Any value object share the properties of
1432 pyasn1 OctetString object.
1433 </p>
1434
1435 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1436 <pre>
1437 >>> from pyasn1.type import univ
1438 >>> someValue = univ.Any(b'\x02\x01\x01')
1439 >>> someValue
1440 Any(b'\x02\x01\x01')
1441 >>> str(someValue)
1442 '\x02\x01\x01'
1443 >>> bytes(someValue)
1444 b'\x02\x01\x01'
1445 >>>
1446 </pre>
1447 </td></tr></table>
1448
1449 <p>
1450 Receiving application is supposed to explicitly deserialize the content of Any
1451 value object, possibly using auxiliary selector for figuring out its ASN.1
1452 type to pick appropriate decoder.
1453 </p>
1454
1455 <p>
1456 There will be some more talk and code snippets covering Any type in the codecs
1457 chapters that follow.
1458 </p>
1459
1460 <a name="1.4"></a>
1461 <h4>
1462 1.4 Subtype constraints
1463 </h4>
1464
1465 <p>
1466 Most ASN.1 types can correspond to an infinite set of values. To adapt to
1467 particular application's data model and needs, ASN.1 provides a mechanism
1468 for limiting the infinite set to values, that make sense in particular case.
1469 </p>
1470
1471 <p>
1472 Imposing value constraints on an ASN.1 type can also be seen as creating
1473 a subtype from its base type.
1474 </p>
1475
1476 <p>
1477 In pyasn1, constraints take shape of immutable objects capable
1478 of evaluating given value against constraint-specific requirements.
1479 Constraint object is a property of pyasn1 type. Like TagSet property,
1480 associated with every pyasn1 type, constraints can never be modified
1481 in place. The only way to modify pyasn1 type constraint is to associate
1482 new constraint object to a new pyasn1 type object.
1483 </p>
1484
1485 <p>
1486 A handful of different flavors of <i>constraints</i> are defined in ASN.1.
1487 We will discuss them one by one in the following chapters and also explain
1488 how to combine and apply them to types.
1489 </p>
1490
1491 <a name="1.4.1"></a>
1492 <h4>
1493 1.4.1 Single value constraint
1494 </h4>
1495
1496 <p>
1497 This kind of constraint allows for limiting type to a finite, specified set
1498 of values.
1499 </p>
1500
1501 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1502 <pre>
1503 DialButton ::= OCTET STRING (
1504 "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
1505 )
1506 </pre>
1507 </td></tr></table>
1508
1509 <p>
1510 Its pyasn1 implementation would look like:
1511 </p>
1512
1513 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1514 <pre>
1515 >>> from pyasn1.type import constraint
1516 >>> c = constraint.SingleValueConstraint(
1517 '0','1','2','3','4','5','6','7','8','9'
1518 )
1519 >>> c
1520 SingleValueConstraint(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
1521 >>> c('0')
1522 >>> c('A')
1523 Traceback (most recent call last):
1524 ...
1525 pyasn1.type.error.ValueConstraintError:
1526 SingleValueConstraint(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) failed at: A
1527 >>>
1528 </pre>
1529 </td></tr></table>
1530
1531 <p>
1532 As can be seen in the snippet above, if a value violates the constraint, an
1533 exception will be thrown. A constrainted pyasn1 type object holds a
1534 reference to a constraint object (or their combination, as will be explained
1535 later) and calls it for value verification.
1536 </p>
1537
1538 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1539 <pre>
1540 >>> from pyasn1.type import univ, constraint
1541 >>> class DialButton(univ.OctetString):
1542 ... subtypeSpec = constraint.SingleValueConstraint(
1543 ... '0','1','2','3','4','5','6','7','8','9'
1544 ... )
1545 >>> DialButton('0')
1546 DialButton(b'0')
1547 >>> DialButton('A')
1548 Traceback (most recent call last):
1549 ...
1550 pyasn1.type.error.ValueConstraintError:
1551 SingleValueConstraint(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) failed at: A
1552 >>>
1553 </pre>
1554 </td></tr></table>
1555
1556 <p>
1557 Constrained pyasn1 value object can never hold a violating value.
1558 </p>
1559
1560 <a name="1.4.2"></a>
1561 <h4>
1562 1.4.2 Value range constraint
1563 </h4>
1564
1565 <p>
1566 A pair of values, compliant to a type to be constrained, denote low and upper
1567 bounds of allowed range of values of a type.
1568 </p>
1569
1570 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1571 <pre>
1572 Teenagers ::= INTEGER (13..19)
1573 </pre>
1574 </td></tr></table>
1575
1576 <p>
1577 And in pyasn1 terms:
1578 </p>
1579
1580 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1581 <pre>
1582 >>> from pyasn1.type import univ, constraint
1583 >>> class Teenagers(univ.Integer):
1584 ... subtypeSpec = constraint.ValueRangeConstraint(13, 19)
1585 >>> Teenagers(14)
1586 Teenagers(14)
1587 >>> Teenagers(20)
1588 Traceback (most recent call last):
1589 ...
1590 pyasn1.type.error.ValueConstraintError:
1591 ValueRangeConstraint(13, 19) failed at: 20
1592 >>>
1593 </pre>
1594 </td></tr></table>
1595
1596 <p>
1597 Value range constraint usually applies numeric types.
1598 </p>
1599
1600 <a name="1.4.3"></a>
1601 <h4>
1602 1.4.3 Size constraint
1603 </h4>
1604
1605 <p>
1606 It is sometimes convenient to set or limit the allowed size of a data item
1607 to be sent from one application to another to manage bandwidth and memory
1608 consumption issues. Size constraint specifies the lower and upper bounds
1609 of the size of a valid value.
1610 </p>
1611
1612 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1613 <pre>
1614 TwoBits ::= BIT STRING (SIZE (2))
1615 </pre>
1616 </td></tr></table>
1617
1618 <p>
1619 Express the same grammar in pyasn1:
1620 </p>
1621
1622 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1623 <pre>
1624 >>> from pyasn1.type import univ, constraint
1625 >>> class TwoBits(univ.BitString):
1626 ... subtypeSpec = constraint.ValueSizeConstraint(2, 2)
1627 >>> TwoBits((1,1))
1628 TwoBits("'11'B")
1629 >>> TwoBits((1,1,0))
1630 Traceback (most recent call last):
1631 ...
1632 pyasn1.type.error.ValueConstraintError:
1633 ValueSizeConstraint(2, 2) failed at: (1, 1, 0)
1634 >>>
1635 </pre>
1636 </td></tr></table>
1637
1638 <p>
1639 Size constraint can be applied to potentially massive values - bit or octet
1640 strings, SEQUENCE OF/SET OF values.
1641 </p>
1642
1643 <a name="1.4.4"></a>
1644 <h4>
1645 1.4.4 Alphabet constraint
1646 </h4>
1647
1648 <p>
1649 The permitted alphabet constraint is similar to Single value constraint
1650 but constraint applies to individual characters of a value.
1651 </p>
1652
1653 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1654 <pre>
1655 MorseCode ::= PrintableString (FROM ("."|"-"|" "))
1656 </pre>
1657 </td></tr></table>
1658
1659 <p>
1660 And in pyasn1:
1661 </p>
1662
1663 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1664 <pre>
1665 >>> from pyasn1.type import char, constraint
1666 >>> class MorseCode(char.PrintableString):
1667 ... subtypeSpec = constraint.PermittedAlphabetConstraint(".", "-", " ")
1668 >>> MorseCode("...---...")
1669 MorseCode('...---...')
1670 >>> MorseCode("?")
1671 Traceback (most recent call last):
1672 ...
1673 pyasn1.type.error.ValueConstraintError:
1674 PermittedAlphabetConstraint(".", "-", " ") failed at: "?"
1675 >>>
1676 </pre>
1677 </td></tr></table>
1678
1679 <p>
1680 Current implementation does not handle ranges of characters in constraint
1681 (FROM "A".."Z" syntax), one has to list the whole set in a range.
1682 </p>
1683
1684 <a name="1.4.5"></a>
1685 <h4>
1686 1.4.5 Constraint combinations
1687 </h4>
1688
1689 <p>
1690 Up to this moment, we used a single constraint per ASN.1 type. The standard,
1691 however, allows for combining multiple individual constraints into
1692 intersections, unions and exclusions.
1693 </p>
1694
1695 <p>
1696 In pyasn1 data model, all of these methods of constraint combinations are
1697 implemented as constraint-like objects holding individual constraint (or
1698 combination) objects. Like terminal constraint objects, combination objects
1699 are capable to perform value verification at its set of enclosed constraints
1700 according to the logic of particular combination.
1701 </p>
1702
1703 <p>
1704 Constraints intersection verification succeeds only if a value is
1705 compliant to each constraint in a set. To begin with, the following
1706 specification will constitute a valid telephone number:
1707 </p>
1708
1709 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1710 <pre>
1711 PhoneNumber ::= NumericString (FROM ("0".."9")) (SIZE 11)
1712 </pre>
1713 </td></tr></table>
1714
1715 <p>
1716 Constraint intersection object serves the logic above:
1717 </p>
1718
1719 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1720 <pre>
1721 >>> from pyasn1.type import char, constraint
1722 >>> class PhoneNumber(char.NumericString):
1723 ... subtypeSpec = constraint.ConstraintsIntersection(
1724 ... constraint.PermittedAlphabetConstraint('0','1','2','3','4','5','6','7',' 8','9'),
1725 ... constraint.ValueSizeConstraint(11, 11)
1726 ... )
1727 >>> PhoneNumber('79039343212')
1728 PhoneNumber('79039343212')
1729 >>> PhoneNumber('?9039343212')
1730 Traceback (most recent call last):
1731 ...
1732 pyasn1.type.error.ValueConstraintError:
1733 ConstraintsIntersection(
1734 PermittedAlphabetConstraint('0','1','2','3','4','5','6','7','8','9'),
1735 ValueSizeConstraint(11, 11)) failed at:
1736 PermittedAlphabetConstraint('0','1','2','3','4','5','6','7','8','9') failed a t: "?039343212"
1737 >>> PhoneNumber('9343212')
1738 Traceback (most recent call last):
1739 ...
1740 pyasn1.type.error.ValueConstraintError:
1741 ConstraintsIntersection(
1742 PermittedAlphabetConstraint('0','1','2','3','4','5','6','7','8','9'),
1743 ValueSizeConstraint(11, 11)) failed at:
1744 ValueSizeConstraint(10, 10) failed at: "9343212"
1745 >>>
1746 </pre>
1747 </td></tr></table>
1748
1749 <p>
1750 Union of constraints works by making sure that a value is compliant
1751 to any of the constraint in a set. For instance:
1752 </p>
1753
1754 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1755 <pre>
1756 CapitalOrSmall ::= IA5String (FROM ('A','B','C') | FROM ('a','b','c'))
1757 </pre>
1758 </td></tr></table>
1759
1760 <p>
1761 It's important to note, that a value must fully comply to any single
1762 constraint in a set. In the specification above, a value of all small or
1763 all capital letters is compliant, but a mix of small&capitals is not.
1764 Here's its pyasn1 analogue:
1765 </p>
1766
1767 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1768 <pre>
1769 >>> from pyasn1.type import char, constraint
1770 >>> class CapitalOrSmall(char.IA5String):
1771 ... subtypeSpec = constraint.ConstraintsUnion(
1772 ... constraint.PermittedAlphabetConstraint('A','B','C'),
1773 ... constraint.PermittedAlphabetConstraint('a','b','c')
1774 ... )
1775 >>> CapitalOrSmall('ABBA')
1776 CapitalOrSmall('ABBA')
1777 >>> CapitalOrSmall('abba')
1778 CapitalOrSmall('abba')
1779 >>> CapitalOrSmall('Abba')
1780 Traceback (most recent call last):
1781 ...
1782 pyasn1.type.error.ValueConstraintError:
1783 ConstraintsUnion(PermittedAlphabetConstraint('A', 'B', 'C'),
1784 PermittedAlphabetConstraint('a', 'b', 'c')) failed at: failed for "Abba"
1785 >>>
1786 </pre>
1787 </td></tr></table>
1788
1789 <p>
1790 Finally, the exclusion constraint simply negates the logic of value
1791 verification at a constraint. In the following example, any integer value
1792 is allowed in a type but not zero.
1793 </p>
1794
1795 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1796 <pre>
1797 NoZero ::= INTEGER (ALL EXCEPT 0)
1798 </pre>
1799 </td></tr></table>
1800
1801 <p>
1802 In pyasn1 the above definition would read:
1803 </p>
1804
1805 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1806 <pre>
1807 >>> from pyasn1.type import univ, constraint
1808 >>> class NoZero(univ.Integer):
1809 ... subtypeSpec = constraint.ConstraintsExclusion(
1810 ... constraint.SingleValueConstraint(0)
1811 ... )
1812 >>> NoZero(1)
1813 NoZero(1)
1814 >>> NoZero(0)
1815 Traceback (most recent call last):
1816 ...
1817 pyasn1.type.error.ValueConstraintError:
1818 ConstraintsExclusion(SingleValueConstraint(0)) failed at: 0
1819 >>>
1820 </pre>
1821 </td></tr></table>
1822
1823 <p>
1824 The depth of such a constraints tree, built with constraint combination objects
1825 at its nodes, has not explicit limit. Value verification is performed in a
1826 recursive manner till a definite solution is found.
1827 </p>
1828
1829 <a name="1.5"></a>
1830 <h4>
1831 1.5 Types relationships
1832 </h4>
1833
1834 <p>
1835 In the course of data processing in an application, it is sometimes
1836 convenient to figure out the type relationships between pyasn1 type or
1837 value objects. Formally, two things influence pyasn1 types relationship:
1838 <i>tag set</i> and <i>subtype constraints</i>. One pyasn1 type is considered
1839 to be a derivative of another if their TagSet and Constraint objects are
1840 a derivation of one another.
1841 </p>
1842
1843 <p>
1844 The following example illustrates the concept (we use the same tagset but
1845 different constraints for simplicity):
1846 </p>
1847
1848 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1849 <pre>
1850 >>> from pyasn1.type import univ, constraint
1851 >>> i1 = univ.Integer(subtypeSpec=constraint.ValueRangeConstraint(3,8))
1852 >>> i2 = univ.Integer(subtypeSpec=constraint.ConstraintsIntersection(
1853 ... constraint.ValueRangeConstraint(3,8),
1854 ... constraint.ValueRangeConstraint(4,7)
1855 ... ) )
1856 >>> i1.isSameTypeWith(i2)
1857 False
1858 >>> i1.isSuperTypeOf(i2)
1859 True
1860 >>> i1.isSuperTypeOf(i1)
1861 True
1862 >>> i2.isSuperTypeOf(i1)
1863 False
1864 >>>
1865 </pre>
1866 </td></tr></table>
1867
1868 <p>
1869 As can be seen in the above code snippet, there are two methods of any pyasn1
1870 type/value object that test types for their relationship:
1871 <b>isSameTypeWith</b>() and <b>isSuperTypeOf</b>(). The former is
1872 self-descriptive while the latter yields true if the argument appears
1873 to be a pyasn1 object which has tagset and constraints derived from those
1874 of the object being called.
1875 </p>
1876
1877 <a name="2"></a>
1878 <h3>
1879 2. Codecs
1880 </h3>
1881
1882 <p>
1883 In ASN.1 context,
1884 <a href=http://en.wikipedia.org/wiki/Codec>codec</a>
1885 is a program that transforms between concrete data structures and a stream
1886 of octets, suitable for transmission over the wire. This serialized form of
1887 data is sometimes called <i>substrate</i> or <i>essence</i>.
1888 </p>
1889
1890 <p>
1891 In pyasn1 implementation, substrate takes shape of Python 3 bytes or
1892 Python 2 string objects.
1893 </p>
1894
1895 <p>
1896 One of the properties of a codec is its ability to cope with incomplete
1897 data and/or substrate what implies codec to be stateful. In other words,
1898 when decoder runs out of substrate and data item being recovered is still
1899 incomplete, stateful codec would suspend and complete data item recovery
1900 whenever the rest of substrate becomes available. Similarly, stateful encoder
1901 would encode data items in multiple steps waiting for source data to
1902 arrive. Codec restartability is especially important when application deals
1903 with large volumes of data and/or runs on low RAM. For an interesting
1904 discussion on codecs options and design choices, refer to
1905 <a href=http://directory.apache.org/subprojects/asn1/>Apache ASN.1 project</a>
1906 .
1907 </p>
1908
1909 <p>
1910 As of this writing, codecs implemented in pyasn1 are all stateless, mostly
1911 to keep the code simple.
1912 </p>
1913
1914 <p>
1915 The pyasn1 package currently supports
1916 <a href=http://en.wikipedia.org/wiki/Basic_encoding_rules>BER</a> codec and
1917 its variations --
1918 <a href=http://en.wikipedia.org/wiki/Canonical_encoding_rules>CER</a> and
1919 <a href=http://en.wikipedia.org/wiki/Distinguished_encoding_rules>DER</a>.
1920 More ASN.1 codecs are planned for implementation in the future.
1921 </p>
1922
1923 <a name="2.1"></a>
1924 <h4>
1925 2.1 Encoders
1926 </h4>
1927
1928 <p>
1929 Encoder is used for transforming pyasn1 value objects into substrate. Only
1930 pyasn1 value objects could be serialized, attempts to process pyasn1 type
1931 objects will cause encoder failure.
1932 </p>
1933
1934 <p>
1935 The following code will create a pyasn1 Integer object and serialize it with
1936 BER encoder:
1937 </p>
1938
1939 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1940 <pre>
1941 >>> from pyasn1.type import univ
1942 >>> from pyasn1.codec.ber import encoder
1943 >>> encoder.encode(univ.Integer(123456))
1944 b'\x02\x03\x01\xe2@'
1945 >>>
1946 </pre>
1947 </td></tr></table>
1948
1949 <p>
1950 BER standard also defines a so-called <i>indefinite length</i> encoding form
1951 which makes large data items processing more memory efficient. It is mostly
1952 useful when encoder does not have the whole value all at once and the
1953 length of the value can not be determined at the beginning of encoding.
1954 </p>
1955
1956 <p>
1957 <i>Constructed encoding</i> is another feature of BER closely related to the
1958 indefinite length form. In essence, a large scalar value (such as ASN.1
1959 character BitString type) could be chopped into smaller chunks by encoder
1960 and transmitted incrementally to limit memory consumption. Unlike indefinite
1961 length case, the length of the whole value must be known in advance when
1962 using constructed, definite length encoding form.
1963 </p>
1964
1965 <p>
1966 Since pyasn1 codecs are not restartable, pyasn1 encoder may only encode data
1967 item all at once. However, even in this case, generating indefinite length
1968 encoding may help a low-memory receiver, running a restartable decoder,
1969 to process a large data item.
1970 </p>
1971
1972 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
1973 <pre>
1974 >>> from pyasn1.type import univ
1975 >>> from pyasn1.codec.ber import encoder
1976 >>> encoder.encode(
1977 ... univ.OctetString('The quick brown fox jumps over the lazy dog'),
1978 ... defMode=False,
1979 ... maxChunkSize=8
1980 ... )
1981 b'$\x80\x04\x08The quic\x04\x08k brown \x04\x08fox jump\x04\x08s over \
1982 t\x04\x08he lazy \x04\x03dog\x00\x00'
1983 >>>
1984 >>> encoder.encode(
1985 ... univ.OctetString('The quick brown fox jumps over the lazy dog'),
1986 ... maxChunkSize=8
1987 ... )
1988 b'$7\x04\x08The quic\x04\x08k brown \x04\x08fox jump\x04\x08s over \
1989 t\x04\x08he lazy \x04\x03dog'
1990 </pre>
1991 </td></tr></table>
1992
1993 <p>
1994 The <b>defMode</b> encoder parameter disables definite length encoding mode,
1995 while the optional <b>maxChunkSize</b> parameter specifies desired
1996 substrate chunk size that influences memory requirements at the decoder's end.
1997 </p>
1998
1999 <p>
2000 To use CER or DER encoders one needs to explicitly import and call them - the
2001 APIs are all compatible.
2002 </p>
2003
2004 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
2005 <pre>
2006 >>> from pyasn1.type import univ
2007 >>> from pyasn1.codec.ber import encoder as ber_encoder
2008 >>> from pyasn1.codec.cer import encoder as cer_encoder
2009 >>> from pyasn1.codec.der import encoder as der_encoder
2010 >>> ber_encoder.encode(univ.Boolean(True))
2011 b'\x01\x01\x01'
2012 >>> cer_encoder.encode(univ.Boolean(True))
2013 b'\x01\x01\xff'
2014 >>> der_encoder.encode(univ.Boolean(True))
2015 b'\x01\x01\xff'
2016 >>>
2017 </pre>
2018 </td></tr></table>
2019
2020 <a name="2.2"></a>
2021 <h4>
2022 2.2 Decoders
2023 </h4>
2024
2025 <p>
2026 In the process of decoding, pyasn1 value objects are created and linked to
2027 each other, based on the information containted in the substrate. Thus,
2028 the original pyasn1 value object(s) are recovered.
2029 </p>
2030
2031 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
2032 <pre>
2033 >>> from pyasn1.type import univ
2034 >>> from pyasn1.codec.ber import encoder, decoder
2035 >>> substrate = encoder.encode(univ.Boolean(True))
2036 >>> decoder.decode(substrate)
2037 (Boolean('True(1)'), b'')
2038 >>>
2039 </pre>
2040 </td></tr></table>
2041
2042 <p>
2043 Commenting on the code snippet above, pyasn1 decoder accepts substrate
2044 as an argument and returns a tuple of pyasn1 value object (possibly
2045 a top-level one in case of constructed object) and unprocessed part
2046 of input substrate.
2047 </p>
2048
2049 <p>
2050 All pyasn1 decoders can handle both definite and indefinite length
2051 encoding modes automatically, explicit switching into one mode
2052 to another is not required.
2053 </p>
2054
2055 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
2056 <pre>
2057 >>> from pyasn1.type import univ
2058 >>> from pyasn1.codec.ber import encoder, decoder
2059 >>> substrate = encoder.encode(
2060 ... univ.OctetString('The quick brown fox jumps over the lazy dog'),
2061 ... defMode=False,
2062 ... maxChunkSize=8
2063 ... )
2064 >>> decoder.decode(substrate)
2065 (OctetString(b'The quick brown fox jumps over the lazy dog'), b'')
2066 >>>
2067 </pre>
2068 </td></tr></table>
2069
2070 <p>
2071 Speaking of BER/CER/DER encoding, in many situations substrate may not contain
2072 all necessary information needed for complete and accurate ASN.1 values
2073 recovery. The most obvious cases include implicitly tagged ASN.1 types
2074 and constrained types.
2075 </p>
2076
2077 <p>
2078 As discussed earlier in this handbook, when an ASN.1 type is implicitly
2079 tagged, previous outermost tag is lost and never appears in substrate.
2080 If it is the base tag that gets lost, decoder is unable to pick type-specific
2081 value decoder at its table of built-in types, and therefore recover
2082 the value part, based only on the information contained in substrate. The
2083 approach taken by pyasn1 decoder is to use a prototype pyasn1 type object (or
2084 a set of them) to <i>guide</i> the decoding process by matching [possibly
2085 incomplete] tags recovered from substrate with those found in prototype pyasn1
2086 type objects (also called pyasn1 specification object further in this paper).
2087 </p>
2088
2089 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
2090 <pre>
2091 >>> from pyasn1.codec.ber import decoder
2092 >>> decoder.decode(b'\x02\x01\x0c', asn1Spec=univ.Integer())
2093 Integer(12), b''
2094 >>>
2095 </pre>
2096 </td></tr></table>
2097
2098 <p>
2099 Decoder would neither modify pyasn1 specification object nor use
2100 its current values (if it's a pyasn1 value object), but rather use it as
2101 a hint for choosing proper decoder and as a pattern for creating new objects:
2102 </p>
2103
2104 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
2105 <pre>
2106 >>> from pyasn1.type import univ, tag
2107 >>> from pyasn1.codec.ber import encoder, decoder
2108 >>> i = univ.Integer(12345).subtype(
2109 ... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 40)
2110 ... )
2111 >>> substrate = encoder.encode(i)
2112 >>> substrate
2113 b'\x9f(\x0209'
2114 >>> decoder.decode(substrate)
2115 Traceback (most recent call last):
2116 ...
2117 pyasn1.error.PyAsn1Error:
2118 TagSet(Tag(tagClass=128, tagFormat=0, tagId=40)) not in asn1Spec
2119 >>> decoder.decode(substrate, asn1Spec=i)
2120 (Integer(12345), b'')
2121 >>>
2122 </pre>
2123 </td></tr></table>
2124
2125 <p>
2126 Notice in the example above, that an attempt to run decoder without passing
2127 pyasn1 specification object fails because recovered tag does not belong
2128 to any of the built-in types.
2129 </p>
2130
2131 <p>
2132 Another important feature of guided decoder operation is the use of
2133 values constraints possibly present in pyasn1 specification object.
2134 To explain this, we will decode a random integer object into generic Integer
2135 and the constrained one.
2136 </p>
2137
2138 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
2139 <pre>
2140 >>> from pyasn1.type import univ, constraint
2141 >>> from pyasn1.codec.ber import encoder, decoder
2142 >>> class DialDigit(univ.Integer):
2143 ... subtypeSpec = constraint.ValueRangeConstraint(0,9)
2144 >>> substrate = encoder.encode(univ.Integer(13))
2145 >>> decoder.decode(substrate)
2146 (Integer(13), b'')
2147 >>> decoder.decode(substrate, asn1Spec=DialDigit())
2148 Traceback (most recent call last):
2149 ...
2150 pyasn1.type.error.ValueConstraintError:
2151 ValueRangeConstraint(0, 9) failed at: 13
2152 >>>
2153 </pre>
2154 </td></tr></table>
2155
2156 <p>
2157 Similarily to encoders, to use CER or DER decoders application has to
2158 explicitly import and call them - all APIs are compatible.
2159 </p>
2160
2161 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
2162 <pre>
2163 >>> from pyasn1.type import univ
2164 >>> from pyasn1.codec.ber import encoder as ber_encoder
2165 >>> substrate = ber_encoder.encode(univ.OctetString('http://pyasn1.sf.net'))
2166 >>>
2167 >>> from pyasn1.codec.ber import decoder as ber_decoder
2168 >>> from pyasn1.codec.cer import decoder as cer_decoder
2169 >>> from pyasn1.codec.der import decoder as der_decoder
2170 >>>
2171 >>> ber_decoder.decode(substrate)
2172 (OctetString(b'http://pyasn1.sf.net'), b'')
2173 >>> cer_decoder.decode(substrate)
2174 (OctetString(b'http://pyasn1.sf.net'), b'')
2175 >>> der_decoder.decode(substrate)
2176 (OctetString(b'http://pyasn1.sf.net'), b'')
2177 >>>
2178 </pre>
2179 </td></tr></table>
2180
2181 <a name="2.2.1"></a>
2182 <h4>
2183 2.2.1 Decoding untagged types
2184 </h4>
2185
2186 <p>
2187 It has already been mentioned, that ASN.1 has two "special case" types:
2188 CHOICE and ANY. They are different from other types in part of
2189 tagging - unless these two are additionally tagged, neither of them will
2190 have their own tag. Therefore these types become invisible in substrate
2191 and can not be recovered without passing pyasn1 specification object to
2192 decoder.
2193 </p>
2194
2195 <p>
2196 To explain the issue, we will first prepare a Choice object to deal with:
2197 </p>
2198
2199 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
2200 <pre>
2201 >>> from pyasn1.type import univ, namedtype
2202 >>> class CodeOrMessage(univ.Choice):
2203 ... componentType = namedtype.NamedTypes(
2204 ... namedtype.NamedType('code', univ.Integer()),
2205 ... namedtype.NamedType('message', univ.OctetString())
2206 ... )
2207 >>>
2208 >>> codeOrMessage = CodeOrMessage()
2209 >>> codeOrMessage.setComponentByName('message', 'my string value')
2210 >>> print(codeOrMessage.prettyPrint())
2211 CodeOrMessage:
2212 message=b'my string value'
2213 >>>
2214 </pre>
2215 </td></tr></table>
2216
2217 <p>
2218 Let's now encode this Choice object and then decode its substrate
2219 with and without pyasn1 specification object:
2220 </p>
2221
2222 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
2223 <pre>
2224 >>> from pyasn1.codec.ber import encoder, decoder
2225 >>> substrate = encoder.encode(codeOrMessage)
2226 >>> substrate
2227 b'\x04\x0fmy string value'
2228 >>> encoder.encode(univ.OctetString('my string value'))
2229 b'\x04\x0fmy string value'
2230 >>>
2231 >>> decoder.decode(substrate)
2232 (OctetString(b'my string value'), b'')
2233 >>> codeOrMessage, substrate = decoder.decode(substrate, asn1Spec=CodeOrMessage( ))
2234 >>> print(codeOrMessage.prettyPrint())
2235 CodeOrMessage:
2236 message=b'my string value'
2237 >>>
2238 </pre>
2239 </td></tr></table>
2240
2241 <p>
2242 First thing to notice in the listing above is that the substrate produced
2243 for our Choice value object is equivalent to the substrate for an OctetString
2244 object initialized to the same value. In other words, any information about
2245 the Choice component is absent in encoding.
2246 </p>
2247
2248 <p>
2249 Sure enough, that kind of substrate will decode into an OctetString object,
2250 unless original Choice type object is passed to decoder to guide the decoding
2251 process.
2252 </p>
2253
2254 <p>
2255 Similarily untagged ANY type behaves differently on decoding phase - when
2256 decoder bumps into an Any object in pyasn1 specification, it stops decoding
2257 and puts all the substrate into a new Any value object in form of an octet
2258 string. Concerned application could then re-run decoder with an additional,
2259 more exact pyasn1 specification object to recover the contents of Any
2260 object.
2261 </p>
2262
2263 <p>
2264 As it was mentioned elsewhere in this paper, Any type allows for incomplete
2265 or changing ASN.1 specification to be handled gracefully by decoder and
2266 applications.
2267 </p>
2268
2269 <p>
2270 To illustrate the working of Any type, we'll have to make the stage
2271 by encoding a pyasn1 object and then putting its substrate into an any
2272 object.
2273 </p>
2274
2275 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
2276 <pre>
2277 >>> from pyasn1.type import univ
2278 >>> from pyasn1.codec.ber import encoder, decoder
2279 >>> innerSubstrate = encoder.encode(univ.Integer(1234))
2280 >>> innerSubstrate
2281 b'\x02\x02\x04\xd2'
2282 >>> any = univ.Any(innerSubstrate)
2283 >>> any
2284 Any(b'\x02\x02\x04\xd2')
2285 >>> substrate = encoder.encode(any)
2286 >>> substrate
2287 b'\x02\x02\x04\xd2'
2288 >>>
2289 </pre>
2290 </td></tr></table>
2291
2292 <p>
2293 As with Choice type encoding, there is no traces of Any type in substrate.
2294 Obviously, the substrate we are dealing with, will decode into the inner
2295 [Integer] component, unless pyasn1 specification is given to guide the
2296 decoder. Continuing previous code:
2297 </p>
2298
2299 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
2300 <pre>
2301 >>> from pyasn1.type import univ
2302 >>> from pyasn1.codec.ber import encoder, decoder
2303
2304 >>> decoder.decode(substrate)
2305 (Integer(1234), b'')
2306 >>> any, substrate = decoder.decode(substrate, asn1Spec=univ.Any())
2307 >>> any
2308 Any(b'\x02\x02\x04\xd2')
2309 >>> decoder.decode(str(any))
2310 (Integer(1234), b'')
2311 >>>
2312 </pre>
2313 </td></tr></table>
2314
2315 <p>
2316 Both CHOICE and ANY types are widely used in practice. Reader is welcome to
2317 take a look at
2318 <a href=http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt>
2319 ASN.1 specifications of X.509 applications</a> for more information.
2320 </p>
2321
2322 <a name="2.2.2"></a>
2323 <h4>
2324 2.2.2 Ignoring unknown types
2325 </h4>
2326
2327 <p>
2328 When dealing with a loosely specified ASN.1 structure, the receiving
2329 end may not be aware of some types present in the substrate. It may be
2330 convenient then to turn decoder into a recovery mode. Whilst there, decoder
2331 will not bail out when hit an unknown tag but rather treat it as an Any
2332 type.
2333 </p>
2334
2335 <table bgcolor="lightgray" border=0 width=100%><TR><TD>
2336 <pre>
2337 >>> from pyasn1.type import univ, tag
2338 >>> from pyasn1.codec.ber import encoder, decoder
2339 >>> taggedInt = univ.Integer(12345).subtype(
2340 ... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 40)
2341 ... )
2342 >>> substrate = encoder.encode(taggedInt)
2343 >>> decoder.decode(substrate)
2344 Traceback (most recent call last):
2345 ...
2346 pyasn1.error.PyAsn1Error: TagSet(Tag(tagClass=128, tagFormat=0, tagId=40)) not i n asn1Spec
2347 >>>
2348 >>> decoder.decode.defaultErrorState = decoder.stDumpRawValue
2349 >>> decoder.decode(substrate)
2350 (Any(b'\x9f(\x0209'), '')
2351 >>>
2352 </pre>
2353 </td></tr></table>
2354
2355 <p>
2356 It's also possible to configure a custom decoder, to handle unknown tags
2357 found in substrate. This can be done by means of <b>defaultRawDecoder</b>
2358 attribute holding a reference to type decoder object. Refer to the source
2359 for API details.
2360 </p>
2361
2362 <a name="3"></a>
2363 <h3>
2364 3. Feedback and getting help
2365 </h3>
2366
2367 <p>
2368 Although pyasn1 software is almost a decade old and used in many production
2369 environments, it still may have bugs and non-implemented pieces. Anyone
2370 who happens to run into such defect is welcome to complain to
2371 <a href=mailto:pyasn1-users@lists.sourceforge.net>pyasn1 mailing list</a>
2372 or better yet fix the issue and send
2373 <a href=mailto:ilya@glas.net>me</a> the patch.
2374 </p>
2375
2376 <p>
2377 Typically, pyasn1 is used for building arbitrary protocol support into
2378 various applications. This involves manual translation of ASN.1 data
2379 structures into their pyasn1 implementations. To save time and effort,
2380 data structures for some of the popular protocols are pre-programmed
2381 and kept for further re-use in form of the
2382 <a href=http://sourceforge.net/projects/pyasn1/files/pyasn1-modules/>
2383 pyasn1-modules package</a>. For instance, many structures for PKI (X.509,
2384 PKCS#*, CRMF, OCSP), LDAP and SNMP are present.
2385 Applications authors are advised to import and use relevant modules
2386 from that package whenever needed protocol structures are already
2387 there. New protocol modules contributions are welcome.
2388 </p>
2389
2390 <p>
2391 And finally, the latest pyasn1 package revision is available for free
2392 download from
2393 <a href=http://sourceforge.net/projects/pyasn1/>project home</a> and
2394 also from the
2395 <a href=http://pypi.python.org/pypi>Python package repository</a>.
2396 </p>
2397
2398 <hr>
2399
2400 </td>
2401 </tr>
2402 </table>
2403 </center>
2404 </body>
2405 </html>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698