1 <html> 2 <title> 3 PyASN1 data model and scalar types 4 </title> 5 <head> 6 </head> 7 <body> 8 <center> 9 <table width=60%> 10 <tr> 11 <td> 12 13 <h3> 14 1. Data model for ASN.1 types 15 </h3> 16 17 <p> 18 All ASN.1 types could be categorized into two groups: scalar (also called 19 simple or primitive) and constructed. The first group is populated by 20 well-known types like Integer or String. Members of constructed group 21 hold other types (simple or constructed) as their inner components, thus 22 they are semantically close to a programming language records or lists. 23 </p> 24 25 <p> 26 In pyasn1, all ASN.1 types and values are implemented as Python objects. 27 The same pyasn1 object can represent either ASN.1 type and/or value 28 depending of the presense of value initializer on object instantiation. 29 We will further refer to these as <i>pyasn1 type object</i> versus <i>pyasn1 30 value object</i>. 31 </p> 32 33 <p> 34 Primitive ASN.1 types are implemented as immutable scalar objects. There values 35 could be used just like corresponding native Python values (integers, 36 strings/bytes etc) and freely mixed with them in expressions. 37 </p> 38 39 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 40 <pre> 41 >>> from pyasn1.type import univ 42 >>> asn1IntegerValue = univ.Integer(12) 43 >>> asn1IntegerValue - 2 44 10 45 >>> univ.OctetString('abc') == 'abc' 46 True # Python 2 47 >>> univ.OctetString(b'abc') == b'abc' 48 True # Python 3 49 </pre> 50 </td></tr></table> 51 52 <p> 53 It would be an error to perform an operation on a pyasn1 type object 54 as it holds no value to deal with: 55 </p> 56 57 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 58 <pre> 59 >>> from pyasn1.type import univ 60 >>> asn1IntegerType = univ.Integer() 61 >>> asn1IntegerType - 2 62 ... 63 pyasn1.error.PyAsn1Error: No value for __coerce__() 64 </pre> 65 </td></tr></table> 66 67 <a name="1.1"></a> 68 <h4> 69 1.1 Scalar types 70 </h4> 71 72 <p> 73 In the sub-sections that follow we will explain pyasn1 mapping to those 74 primitive ASN.1 types. Both, ASN.1 notation and corresponding pyasn1 75 syntax will be given in each case. 76 </p> 77 78 <a name="1.1.1"></a> 79 <h4> 80 1.1.1 Boolean type 81 </h4> 82 83 <p> 84 This is the simplest type those values could be either True or False. 85 </p> 86 87 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 88 <pre> 89 ;; type specification 90 FunFactorPresent ::= BOOLEAN 91 92 ;; values declaration and assignment 93 pythonFunFactor FunFactorPresent ::= TRUE 94 cobolFunFactor FunFactorPresent :: FALSE 95 </pre> 96 </td></tr></table> 97 98 <p> 99 And here's pyasn1 version of it: 100 </p> 101 102 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 103 <pre> 104 >>> from pyasn1.type import univ 105 >>> class FunFactorPresent(univ.Boolean): pass 106 ... 107 >>> pythonFunFactor = FunFactorPresent(True) 108 >>> cobolFunFactor = FunFactorPresent(False) 109 >>> pythonFunFactor 110 FunFactorPresent('True(1)') 111 >>> cobolFunFactor 112 FunFactorPresent('False(0)') 113 >>> pythonFunFactor == cobolFunFactor 114 False 115 >>> 116 </pre> 117 </td></tr></table> 118 119 <a name="1.1.2"></a> 120 <h4> 121 1.1.2 Null type 122 </h4> 123 124 <p> 125 The NULL type is sometimes used to express the absense of any information. 126 </p> 127 128 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 129 <pre> 130 ;; type specification 131 Vote ::= CHOICE { 132 agreed BOOLEAN, 133 skip NULL 134 } 135 </td></tr></table> 136 137 ;; value declaration and assignment 138 myVote Vote ::= skip:NULL 139 </pre> 140 141 <p> 142 We will explain the CHOICE type later in this paper, meanwhile the NULL 143 type: 144 </p> 145 146 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 147 <pre> 148 >>> from pyasn1.type import univ 149 >>> skip = univ.Null() 150 >>> skip 151 Null('') 152 >>> 153 </pre> 154 </td></tr></table> 155 156 <a name="1.1.3"></a> 157 <h4> 158 1.1.3 Integer type 159 </h4> 160 161 <p> 162 ASN.1 defines the values of Integer type as negative or positive of whatever 163 length. This definition plays nicely with Python as the latter places no 164 limit on Integers. However, some ASN.1 implementations may impose certain 165 limits of integer value ranges. Keep that in mind when designing new 166 data structures. 167 </p> 168 169 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 170 <pre> 171 ;; values specification 172 age-of-universe INTEGER ::= 13750000000 173 mean-martian-surface-temperature INTEGER ::= -63 174 </pre> 175 </td></tr></table> 176 177 <p> 178 A rather strigntforward mapping into pyasn1: 179 </p> 180 181 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 182 <pre> 183 >>> from pyasn1.type import univ 184 >>> ageOfUniverse = univ.Integer(13750000000) 185 >>> ageOfUniverse 186 Integer(13750000000) 187 >>> 188 >>> meanMartianSurfaceTemperature = univ.Integer(-63) 189 >>> meanMartianSurfaceTemperature 190 Integer(-63) 191 >>> 192 </pre> 193 </td></tr></table> 194 195 <p> 196 ASN.1 allows to assign human-friendly names to particular values of 197 an INTEGER type. 198 </p> 199 200 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 201 <pre> 202 Temperature ::= INTEGER { 203 freezing(0), 204 boiling(100) 205 } 206 </pre> 207 </td></tr></table> 208 209 <p> 210 The Temperature type expressed in pyasn1: 211 </p> 212 213 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 214 <pre> 215 >>> from pyasn1.type import univ, namedval 216 >>> class Temperature(univ.Integer): 217 ... namedValues = namedval.NamedValues(('freezing', 0), ('boiling', 100)) 218 ... 219 >>> t = Temperature(0) 220 >>> t 221 Temperature('freezing(0)') 222 >>> t + 1 223 Temperature(1) 224 >>> t + 100 225 Temperature('boiling(100)') 226 >>> t = Temperature('boiling') 227 >>> t 228 Temperature('boiling(100)') 229 >>> Temperature('boiling') / 2 230 Temperature(50) 231 >>> -1 < Temperature('freezing') 232 True 233 >>> 47 > Temperature('boiling') 234 False 235 >>> 236 </pre> 237 </td></tr></table> 238 239 <p> 240 These values labels have no effect on Integer type operations, any value 241 still could be assigned to a type (information on value constraints will 242 follow further in this paper). 243 </p> 244 245 <a name="1.1.4"></a> 246 <h4> 247 1.1.4 Enumerated type 248 </h4> 249 250 <p> 251 ASN.1 Enumerated type differs from an Integer type in a number of ways. 252 Most important is that its instance can only hold a value that belongs 253 to a set of values specified on type declaration. 254 </p> 255 256 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 257 <pre> 258 error-status ::= ENUMERATED { 259 no-error(0), 260 authentication-error(10), 261 authorization-error(20), 262 general-failure(51) 263 } 264 </pre> 265 </td></tr></table> 266 267 <p> 268 When constructing Enumerated type we will use two pyasn1 features: values 269 labels (as mentioned above) and value constraint (will be described in 270 more details later on). 271 </p> 272 273 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 274 <pre> 275 >>> from pyasn1.type import univ, namedval, constraint 276 >>> class ErrorStatus(univ.Enumerated): 277 ... namedValues = namedval.NamedValues( 278 ... ('no-error', 0), 279 ... ('authentication-error', 10), 280 ... ('authorization-error', 20), 281 ... ('general-failure', 51) 282 ... ) 283 ... subtypeSpec = univ.Enumerated.subtypeSpec + \ 284 ... constraint.SingleValueConstraint(0, 10, 20, 51) 285 ... 286 >>> errorStatus = univ.ErrorStatus('no-error') 287 >>> errorStatus 288 ErrorStatus('no-error(0)') 289 >>> errorStatus == univ.ErrorStatus('general-failure') 290 False 291 >>> univ.ErrorStatus('non-existing-state') 292 Traceback (most recent call last): 293 ... 294 pyasn1.error.PyAsn1Error: Can't coerce non-existing-state into integer 295 >>> 296 </pre> 297 </td></tr></table> 298 299 <p> 300 Particular integer values associated with Enumerated value states 301 have no meaning. They should not be used as such or in any kind of 302 math operation. Those integer values are only used by codecs to 303 transfer state from one entity to another. 304 </p> 305 306 <a name="1.1.5"></a> 307 <h4> 308 1.1.5 Real type 309 </h4> 310 311 <p> 312 Values of the Real type are a three-component tuple of mantissa, base and 313 exponent. All three are integers. 314 </p> 315 316 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 317 <pre> 318 pi ::= REAL { mantissa 314159, base 10, exponent -5 } 319 </pre> 320 </td></tr></table> 321 322 <p> 323 Corresponding pyasn1 objects can be initialized with either a three-component 324 tuple or a Python float. Infinite values could be expressed in a way, 325 compatible with Python float type. 326 327 </p> 328 329 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 330 <pre> 331 >>> from pyasn1.type import univ 332 >>> pi = univ.Real((314159, 10, -5)) 333 >>> pi 334 Real((314159, 10,-5)) 335 >>> float(pi) 336 3.14159 337 >>> pi == univ.Real(3.14159) 338 True 339 >>> univ.Real('inf') 340 Real('inf') 341 >>> univ.Real('-inf') == float('-inf') 342 True 343 >>> 344 </pre> 345 </td></tr></table> 346 347 <p> 348 If a Real object is initialized from a Python float or yielded by a math 349 operation, the base is set to decimal 10 (what affects encoding). 350 </p> 351 352 <a name="1.1.6"></a> 353 <h4> 354 1.1.6 Bit string type 355 </h4> 356 357 <p> 358 ASN.1 BIT STRING type holds opaque binary data of an arbitrarily length. 359 A BIT STRING value could be initialized by either a binary (base 2) or 360 hex (base 16) value. 361 </p> 362 363 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 364 <pre> 365 public-key BIT STRING ::= '1010111011110001010110101101101 366 1011000101010000010110101100010 367 0110101010000111101010111111110'B 368 369 signature BIT STRING ::= 'AF01330CD932093392100B39FF00DE0'H 370 </pre> 371 </td></tr></table> 372 373 <p> 374 The pyasn1 BitString objects can initialize from native ASN.1 notation 375 (base 2 or base 16 strings) or from a Python tuple of binary components. 376 </p> 377 378 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 379 <pre> 380 >>> from pyasn1.type import univ 381 >>> publicKey = univ.BitString( 382 ... "'1010111011110001010110101101101" 383 ... "1011000101010000010110101100010" 384 ... "0110101010000111101010111111110'B" 385 ) 386 >>> publicKey 387 BitString("'10101110111100010101101011011011011000101010000010110101100010\ 388 0110101010000111101010111111110'B") 389 >>> signature = univ.BitString( 390 ... "'AF01330CD932093392100B39FF00DE0'H" 391 ... ) 392 >>> signature 393 BitString("'101011110000000100110011000011001101100100110010000010010011001\ 394 1100100100001000000001011001110011111111100000000110111100000'B") 395 >>> fingerprint = univ.BitString( 396 ... (1, 0, 1, 1 ,0, 1, 1, 1, 0, 1, 0, 1) 397 ... ) 398 >>> fingerprint 399 BitString("'101101110101'B") 400 >>> 401 </pre> 402 </td></tr></table> 403 404 <p> 405 Another BIT STRING initialization method supported by ASN.1 notation 406 is to specify only 1-th bits along with their human-friendly label 407 and bit offset relative to the beginning of the bit string. With this 408 method, all not explicitly mentioned bits are doomed to be zeros. 409 </p> 410 411 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 412 <pre> 413 bit-mask BIT STRING ::= { 414 read-flag(0), 415 write-flag(2), 416 run-flag(4) 417 } 418 </pre> 419 </td></tr></table> 420 421 <p> 422 To express this in pyasn1, we will employ the named values feature (as with 423 Enumeration type). 424 </p> 425 426 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 427 <pre> 428 >>> from pyasn1.type import univ, namedval 429 >>> class BitMask(univ.BitString): 430 ... namedValues = namedval.NamedValues( 431 ... ('read-flag', 0), 432 ... ('write-flag', 2), 433 ... ('run-flag', 4) 434 ... ) 435 >>> bitMask = BitMask('read-flag,run-flag') 436 >>> bitMask 437 BitMask("'10001'B") 438 >>> tuple(bitMask) 439 (1, 0, 0, 0, 1) 440 >>> bitMask[4] 441 1 442 >>> 443 </pre> 444 </td></tr></table> 445 446 <p> 447 The BitString objects mimic the properties of Python tuple type in part 448 of immutable sequence object protocol support. 449 </p> 450 451 <a name="1.1.7"></a> 452 <h4> 453 1.1.7 OctetString type 454 </h4> 455 456 <p> 457 The OCTET STRING type is a confusing subject. According to ASN.1 458 specification, this type is similar to BIT STRING, the major difference 459 is that the former operates in 8-bit chunks of data. What is important 460 to note, is that OCTET STRING was NOT designed to handle text strings - the 461 standard provides many other types specialized for text content. For that 462 reason, ASN.1 forbids to initialize OCTET STRING values with "quoted text 463 strings", only binary or hex initializers, similar to BIT STRING ones, 464 are allowed. 465 </p> 466 467 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 468 <pre> 469 thumbnail OCTET STRING ::= '1000010111101110101111000000111011'B 470 thumbnail OCTET STRING ::= 'FA9823C43E43510DE3422'H 471 </pre> 472 </td></tr></table> 473 474 <p> 475 However, ASN.1 users (e.g. protocols designers) seem to ignore the original 476 purpose of the OCTET STRING type - they used it for handling all kinds of 477 data, including text strings. 478 </p> 479 480 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 481 <pre> 482 welcome-message OCTET STRING ::= "Welcome to ASN.1 wilderness!" 483 </pre> 484 </td></tr></table> 485 486 <p> 487 In pyasn1, we have taken a liberal approach and allowed both BIT STRING 488 style and quoted text initializers for the OctetString objects. To avoid 489 possible collisions, quoted text is the default initialization syntax. 490 </p> 491 492 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 493 <pre> 494 >>> from pyasn1.type import univ 495 >>> thumbnail = univ.OctetString( 496 ... binValue='1000010111101110101111000000111011' 497 ... ) 498 >>> thumbnail 499 OctetString(hexValue='85eebcec0') 500 >>> thumbnail = univ.OctetString( 501 ... hexValue='FA9823C43E43510DE3422' 502 ... ) 503 >>> thumbnail 504 OctetString(hexValue='fa9823c43e4351de34220') 505 >>> 506 </pre> 507 </td></tr></table> 508 509 <p> 510 Most frequent usage of the OctetString class is to instantiate it with 511 a text string. 512 </p> 513 514 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 515 <pre> 516 >>> from pyasn1.type import univ 517 >>> welcomeMessage = univ.OctetString('Welcome to ASN.1 wilderness!') 518 >>> welcomeMessage 519 OctetString(b'Welcome to ASN.1 wilderness!') 520 >>> print('%s' % welcomeMessage) 521 Welcome to ASN.1 wilderness! 522 >>> welcomeMessage[11:16] 523 OctetString(b'ASN.1') 524 >>> 525 </pre> 526 </td></tr></table> 527 528 <p> 529 OctetString objects support the immutable sequence object protocol. 530 In other words, they behave like Python 3 bytes (or Python 2 strings). 531 </p> 532 533 <p> 534 When running pyasn1 on Python 3, it's better to use the bytes objects for 535 OctetString instantiation, as it's more reliable and efficient. 536 </p> 537 538 <p> 539 Additionally, OctetString's can also be instantiated with a sequence of 540 8-bit integers (ASCII codes). 541 </p> 542 543 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 544 <pre> 545 >>> univ.OctetString((77, 101, 101, 103, 111)) 546 OctetString(b'Meego') 547 </pre> 548 </td></tr></table> 549 550 <p> 551 It is sometimes convenient to express OctetString instances as 8-bit 552 characters (Python 3 bytes or Python 2 strings) or 8-bit integers. 553 </p> 554 555 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 556 <pre> 557 >>> octetString = univ.OctetString('ABCDEF') 558 >>> octetString.asNumbers() 559 (65, 66, 67, 68, 69, 70) 560 >>> octetString.asOctets() 561 b'ABCDEF' 562 </pre> 563 </td></tr></table> 564 565 <a name="1.1.8"></a> 566 <h4> 567 1.1.8 ObjectIdentifier type 568 </h4> 569 570 <p> 571 Values of the OBJECT IDENTIFIER type are sequences of integers that could 572 be used to identify virtually anything in the world. Various ASN.1-based 573 protocols employ OBJECT IDENTIFIERs for their own identification needs. 574 </p> 575 576 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 577 <pre> 578 internet-id OBJECT IDENTIFIER ::= { 579 iso(1) identified-organization(3) dod(6) internet(1) 580 } 581 </pre> 582 </td></tr></table> 583 584 <p> 585 One of the natural ways to map OBJECT IDENTIFIER type into a Python 586 one is to use Python tuples of integers. So this approach is taken by 587 pyasn1. 588 </p> 589 590 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 591 <pre> 592 >>> from pyasn1.type import univ 593 >>> internetId = univ.ObjectIdentifier((1, 3, 6, 1)) 594 >>> internetId 595 ObjectIdentifier('1.3.6.1') 596 >>> internetId[2] 597 6 598 >>> internetId[1:3] 599 ObjectIdentifier('3.6') 600 </pre> 601 </td></tr></table> 602 603 <p> 604 A more human-friendly "dotted" notation is also supported. 605 </p> 606 607 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 608 <pre> 609 >>> from pyasn1.type import univ 610 >>> univ.ObjectIdentifier('1.3.6.1') 611 ObjectIdentifier('1.3.6.1') 612 </pre> 613 </td></tr></table> 614 615 <p> 616 Symbolic names of the arcs of object identifier, sometimes present in 617 ASN.1 specifications, are not preserved and used in pyasn1 objects. 618 </p> 619 620 <p> 621 The ObjectIdentifier objects mimic the properties of Python tuple type in 622 part of immutable sequence object protocol support. 623 </p> 624 625 <a name="1.1.9"></a> 626 <h4> 627 1.1.9 Character string types 628 </h4> 629 630 <p> 631 ASN.1 standard introduces a diverse set of text-specific types. All of them 632 were designed to handle various types of characters. Some of these types seem 633 be obsolete nowdays, as their target technologies are gone. Another issue 634 to be aware of is that raw OCTET STRING type is sometimes used in practice 635 by ASN.1 users instead of specialized character string types, despite 636 explicit prohibition imposed by ASN.1 specification. 637 </p> 638 639 <p> 640 The two types are specific to ASN.1 are NumericString and PrintableString. 641 </p> 642 643 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 644 <pre> 645 welcome-message ::= PrintableString { 646 "Welcome to ASN.1 text types" 647 } 648 649 dial-pad-numbers ::= NumericString { 650 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" 651 } 652 </pre> 653 </td></tr></table> 654 655 <p> 656 Their pyasn1 implementations are: 657 </p> 658 659 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 660 <pre> 661 >>> from pyasn1.type import char 662 >>> '%s' % char.PrintableString("Welcome to ASN.1 text types") 663 'Welcome to ASN.1 text types' 664 >>> dialPadNumbers = char.NumericString( 665 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" 666 ) 667 >>> dialPadNumbers 668 NumericString(b'0123456789') 669 >>> 670 </pre> 671 </td></tr></table> 672 673 <p> 674 The following types came to ASN.1 from ISO standards on character sets. 675 </p> 676 677 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 678 <pre> 679 >>> from pyasn1.type import char 680 >>> char.VisibleString("abc") 681 VisibleString(b'abc') 682 >>> char.IA5String('abc') 683 IA5String(b'abc') 684 >>> char.TeletexString('abc') 685 TeletexString(b'abc') 686 >>> char.VideotexString('abc') 687 VideotexString(b'abc') 688 >>> char.GraphicString('abc') 689 GraphicString(b'abc') 690 >>> char.GeneralString('abc') 691 GeneralString(b'abc') 692 >>> 693 </pre> 694 </td></tr></table> 695 696 <p> 697 The last three types are relatively recent addition to the family of 698 character string types: UniversalString, BMPString, UTF8String. 699 </p> 700 701 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 702 <pre> 703 >>> from pyasn1.type import char 704 >>> char.UniversalString("abc") 705 UniversalString(b'abc') 706 >>> char.BMPString('abc') 707 BMPString(b'abc') 708 >>> char.UTF8String('abc') 709 UTF8String(b'abc') 710 >>> utf8String = char.UTF8String(' ') 711 >>> utf8String 712 UTF8String(b'\xd0\xa3 \xd0\xbf\xd0\xbe\xd0\xbf\xd0\xb0 \xd0\xb1\xd1\x8b\xd0\xbb\xd0\xb0 \ 713 \xd1\x81\xd0\xbe\xd0\xb1\xd0\xb0\xd0\xba\xd0\xb0') 714 >>> print(utf8String) 715 716 >>> 717 </pre> 718 </td></tr></table> 719 720 <p> 721 In pyasn1, all character type objects behave like Python strings. None of 722 them is currently constrained in terms of valid alphabet so it's up to 723 the data source to keep an eye on data validation for these types. 724 </p> 725 726 <a name="1.1.10"></a> 727 <h4> 728 1.1.10 Useful types 729 </h4> 730 731 <p> 732 There are three so-called useful types defined in the standard: 733 ObjectDescriptor, GeneralizedTime, UTCTime. They all are subtypes 734 of GraphicString or VisibleString types therefore useful types are 735 character string types. 736 </p> 737 738 <p> 739 It's advised by the ASN.1 standard to have an instance of ObjectDescriptor 740 type holding a human-readable description of corresponding instance of 741 OBJECT IDENTIFIER type. There are no formal linkage between these instances 742 and provision for ObjectDescriptor uniqueness in the standard. 743 </p> 744 745 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 746 <pre> 747 >>> from pyasn1.type import useful 748 >>> descrBER = useful.ObjectDescriptor( 749 "Basic encoding of a single ASN.1 type" 750 ) 751 >>> 752 </pre> 753 </td></tr></table> 754 755 <p> 756 GeneralizedTime and UTCTime types are designed to hold a human-readable 757 timestamp in a universal and unambiguous form. The former provides 758 more flexibility in notation while the latter is more strict but has 759 Y2K issues. 760 </p> 761 762 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 763 <pre> 764 ;; Mar 8 2010 12:00:00 MSK 765 moscow-time GeneralizedTime ::= "20110308120000.0" 766 ;; Mar 8 2010 12:00:00 UTC 767 utc-time GeneralizedTime ::= "201103081200Z" 768 ;; Mar 8 1999 12:00:00 UTC 769 utc-time UTCTime ::= "9803081200Z" 770 </pre> 771 </td></tr></table> 772 773 <table bgcolor="lightgray" border=0 width=100%><TR><TD> 774 <pre> 775 >>> from pyasn1.type import useful 776 >>> moscowTime = useful.GeneralizedTime("20110308120000.0") 777 >>> utcTime = useful.UTCTime("9803081200Z") 778 >>> 779 </pre> 780 </td></tr></table> 781 782 <p> 783 Despite their intended use, these types possess no special, time-related, 784 handling in pyasn1. They are just printable strings. 785 </p> 786 787 <hr> 788 789 </td> 790 </tr> 791 </table> 792 </center> 793 </body> 794 </html> 795