OLD | NEW |
(Empty) | |
| 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> |
OLD | NEW |