]> Cypherpunks.ru repositories - pyderasn.git/blob - doc/examples.rst
Fix defines documentation example usage
[pyderasn.git] / doc / examples.rst
1 Examples
2 ========
3
4 .. contents::
5
6 Schema definition
7 -----------------
8
9 Let's try to parse X.509 certificate. We have to define our structures
10 based on ASN.1 schema descriptions.
11
12 .. list-table::
13    :header-rows: 1
14
15    * - ASN.1 specification
16      - pyderasn's code
17    * - ::
18
19             Certificate  ::=  SEQUENCE  {
20                 tbsCertificate       TBSCertificate,
21                 signatureAlgorithm   AlgorithmIdentifier,
22                 signatureValue       BIT STRING  }
23      - ::
24
25             class Certificate(Sequence):
26                 schema = (
27                     ("tbsCertificate", TBSCertificate()),
28                     ("signatureAlgorithm", AlgorithmIdentifier()),
29                     ("signatureValue", BitString()),
30                 )
31    * - ::
32
33             AlgorithmIdentifier  ::=  SEQUENCE  {
34                 algorithm    OBJECT IDENTIFIER,
35                 parameters   ANY DEFINED BY algorithm OPTIONAL  }
36      - ::
37
38             class AlgorithmIdentifier(Sequence):
39                 schema = (
40                     ("algorithm", ObjectIdentifier()),
41                     ("parameters", Any(optional=True)),
42                 )
43    * - ::
44
45             TBSCertificate  ::=  SEQUENCE  {
46                 version         [0]  EXPLICIT Version DEFAULT v1,
47                 serialNumber         CertificateSerialNumber,
48                 signature            AlgorithmIdentifier,
49                 issuer               Name,
50                 validity             Validity,
51                 subject              Name,
52                 subjectPublicKeyInfo SubjectPublicKeyInfo,
53                 issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
54                 subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
55                 extensions      [3]  EXPLICIT Extensions OPTIONAL  }
56      - ::
57
58             class TBSCertificate(Sequence):
59                 schema = (
60                     ("version", Version(expl=tag_ctxc(0), default="v1")),
61                     ("serialNumber", CertificateSerialNumber()),
62                     ("signature", AlgorithmIdentifier()),
63                     ("issuer", Name()),
64                     ("validity", Validity()),
65                     ("subject", Name()),
66                     ("subjectPublicKeyInfo", SubjectPublicKeyInfo()),
67                     ("issuerUniqueID", UniqueIdentifier(impl=tag_ctxp(1), optional=True)),
68                     ("subjectUniqueID", UniqueIdentifier(impl=tag_ctxp(2), optional=True)),
69                     ("extensions", Extensions(expl=tag_ctxc(3), optional=True)),
70                 )
71    * - ::
72
73             Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
74      - ::
75
76             class Version(Integer):
77                 schema = (("v1", 0), ("v2", 1), ("v3", 2))
78    * - ::
79
80             CertificateSerialNumber  ::=  INTEGER
81      - ::
82
83             class CertificateSerialNumber(Integer):
84                 pass
85    * - ::
86
87             Validity ::= SEQUENCE {
88                 notBefore      Time,
89                 notAfter       Time }
90             Time ::= CHOICE {
91                 utcTime        UTCTime,
92                 generalTime    GeneralizedTime }
93      - ::
94
95             class Validity(Sequence):
96                 schema = (
97                     ("notBefore", Time()),
98                     ("notAfter", Time()),
99                 )
100             class Time(Choice):
101                 schema = (
102                     ("utcTime", UTCTime()),
103                     ("generalTime", GeneralizedTime()),
104                 )
105    * - ::
106
107             SubjectPublicKeyInfo  ::=  SEQUENCE  {
108                 algorithm            AlgorithmIdentifier,
109                 subjectPublicKey     BIT STRING  }
110      - ::
111
112             class SubjectPublicKeyInfo(Sequence):
113                 schema = (
114                     ("algorithm", AlgorithmIdentifier()),
115                     ("subjectPublicKey", BitString()),
116                 )
117    * - ::
118
119             UniqueIdentifier  ::=  BIT STRING
120      - ::
121
122             class UniqueIdentifier(BitString):
123                 pass
124    * - ::
125
126             Name ::= CHOICE { rdnSequence  RDNSequence }
127
128             RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
129
130             RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
131
132             AttributeTypeAndValue ::= SEQUENCE { type AttributeType, value AttributeValue }
133
134             AttributeType ::= OBJECT IDENTIFIER
135
136             AttributeValue ::= ANY -- DEFINED BY AttributeType
137      - ::
138
139             class Name(Choice):
140                 schema = (("rdnSequence", RDNSequence()),)
141             class RDNSequence(SequenceOf):
142                 schema = RelativeDistinguishedName()
143             class RelativeDistinguishedName(SetOf):
144                 schema = AttributeTypeAndValue()
145                 bounds = (1, float("+inf"))
146             class AttributeTypeAndValue(Sequence):
147                 schema = (
148                     ("type", AttributeType()),
149                     ("value", AttributeValue()),
150                 )
151             class AttributeType(ObjectIdentifier):
152                 pass
153             class AttributeValue(Any):
154                 pass
155    * - ::
156
157             Extensions ::=  SEQUENCE SIZE (1..MAX) OF Extension
158
159             Extension  ::=  SEQUENCE  {
160                 extnID      OBJECT IDENTIFIER,
161                 critical    BOOLEAN DEFAULT FALSE,
162                 extnValue   OCTET STRING
163                 }
164      - ::
165
166             class Extensions(SequenceOf):
167                 schema = Extension()
168                 bounds = (1, float("+inf"))
169             class Extension(Sequence):
170                 schema = (
171                     ("extnID", ObjectIdentifier()),
172                     ("critical", Boolean(default=False)),
173                     ("extnValue", OctetString()),
174                 )
175
176 We are ready to decode PayPal's certificate from Go `encoding/asn1
177 <https://golang.org/pkg/encoding/asn1/>`__ test suite (assuming that
178 it's DER encoded representation is already in ``raw`` variable)::
179
180     >>> crt, tail = Certificate().decode(raw)
181     >>> crt
182     Certificate SEQUENCE[tbsCertificate: TBSCertificate SEQUENCE[
183         version: [0] EXPLICIT Version INTEGER v3 OPTIONAL;
184         serialNumber: CertificateSerialNumber INTEGER 61595;
185         signature: AlgorithmIdentifier SEQUENCE[OBJECT IDENTIFIER 1.2.840.113549.1.1.5...
186
187 Pretty printing
188 ---------------
189
190 There is huge output. Let's pretty print it::
191
192     >>> print(pprint(crt))
193         0   [1,3,1604] Certificate SEQUENCE
194         4   [1,3,1453]  . tbsCertificate: TBSCertificate SEQUENCE
195        10-2 [1,1,   1]  . . version: [0] EXPLICIT Version INTEGER v3 OPTIONAL
196        13   [1,1,   3]  . . serialNumber: CertificateSerialNumber INTEGER 61595
197        18   [1,1,  13]  . . signature: AlgorithmIdentifier SEQUENCE
198        20   [1,1,   9]  . . . algorithm: OBJECT IDENTIFIER 1.2.840.113549.1.1.5
199        31   [0,0,   2]  . . . parameters: [UNIV 5] ANY OPTIONAL
200                         . . . . 05:00
201        33   [0,0, 278]  . . issuer: Name CHOICE rdnSequence
202        33   [1,3, 274]  . . . rdnSequence: RDNSequence SEQUENCE OF
203        37   [1,1,  11]  . . . . 0: RelativeDistinguishedName SET OF
204        39   [1,1,   9]  . . . . . 0: AttributeTypeAndValue SEQUENCE
205        41   [1,1,   3]  . . . . . . type: AttributeType OBJECT IDENTIFIER 2.5.4.6
206        46   [0,0,   4]  . . . . . . value: [UNIV 19] AttributeValue ANY
207                         . . . . . . . 13:02:45:53
208     [...]
209      1461   [1,1,  13]  . signatureAlgorithm: AlgorithmIdentifier SEQUENCE
210      1463   [1,1,   9]  . . algorithm: OBJECT IDENTIFIER 1.2.840.113549.1.1.5
211      1474   [0,0,   2]  . . parameters: [UNIV 5] ANY OPTIONAL
212                         . . . 05:00
213      1476   [1,2, 129]  . signatureValue: BIT STRING 1024 bits
214                         . . 68:EE:79:97:97:DD:3B:EF:16:6A:06:F2:14:9A:6E:CD
215                         . . 9E:12:F7:AA:83:10:BD:D1:7C:98:FA:C7:AE:D4:0E:2C
216      [...]
217
218     Trailing data: 0a
219
220 Let's parse that output, human::
221
222        10-2 [1,1,   1]    . . version: [0] EXPLICIT Version INTEGER v3 OPTIONAL
223        ^  ^  ^ ^    ^     ^   ^        ^            ^       ^       ^  ^
224        0  1  2 3    4     5   6        7            8       9       10 11
225
226 ::
227
228        20   [1,1,   9]    . . . algorithm: OBJECT IDENTIFIER 1.2.840.113549.1.1.5
229        ^     ^ ^    ^     ^     ^          ^                 ^
230        0     2 3    4     5     6          9                 10
231
232 ::
233
234        33   [0,0, 278]    . . issuer: Name CHOICE rdnSequence
235        ^     ^ ^    ^     ^   ^       ^    ^      ^
236        0     2 3    4     5   6       8    9      10
237
238 ::
239
240        52-2∞ B [1,1,1054]∞  . . . . eContent: [0] EXPLICIT BER OCTET STRING 1046 bytes
241              ^           ^                                 ^   ^            ^
242             12          13                                14   9            10
243
244 :0:
245  Offset of the object, where its DER/BER encoding begins.
246  Pay attention that it does **not** include explicit tag.
247 :1:
248  If explicit tag exists, then this is its length (tag + encoded length).
249 :2:
250  Length of object's tag. For example CHOICE does not have its own tag,
251  so it is zero.
252 :3:
253  Length of encoded length.
254 :4:
255  Length of encoded value.
256 :5:
257  Visual indentation to show the depth of object in the hierarchy.
258 :6:
259  Object's name inside SEQUENCE/CHOICE.
260 :7:
261  If either IMPLICIT or EXPLICIT tag is set, then it will be shown
262  here. "IMPLICIT" is omitted.
263 :8:
264  Object's class name, if set. Omitted if it is just an ordinary simple
265  value (like with ``algorithm`` in example above).
266 :9:
267  Object's ASN.1 type.
268 :10:
269  Object's value, if set. Can consist of multiple words (like OCTET/BIT
270  STRINGs above). We see ``v3`` value in Version, because it is named.
271  ``rdnSequence`` is the choice of CHOICE type.
272 :11:
273  Possible other flags like OPTIONAL and DEFAULT, if value equals to the
274  default one, specified in the schema.
275 :12:
276  Shows does object contains any kind of BER encoded data (possibly
277  Sequence holding BER-encoded underlying value).
278 :13:
279  Only applicable to BER encoded data. Indefinite length encoding mark.
280 :14:
281  Only applicable to BER encoded data. If object has BER-specific
282  encoding, then ``BER`` will be shown. It does not depend on indefinite
283  length encoding. ``EOC``, ``BOOLEAN``, ``BIT STRING``, ``OCTET STRING``
284  (and its derivatives), ``SET``, ``SET OF`` could be BERed.
285
286 As command line utility
287 -----------------------
288
289 You can decode DER/BER files using command line abilities and get the
290 same picture as above by executing::
291
292     % python -m pyderasn --schema tests.test_crts:Certificate path/to/file
293
294 If there is no schema for you file, then you can try parsing it without,
295 but of course IMPLICIT tags will often make it impossible. But result is
296 good enough for the certificate above::
297
298     % python -m pyderasn path/to/file
299         0   [1,3,1604]  . >: SEQUENCE OF
300         4   [1,3,1453]  . . >: SEQUENCE OF
301         8   [0,0,   5]  . . . . >: [0] ANY
302                         . . . . . A0:03:02:01:02
303        13   [1,1,   3]  . . . . >: INTEGER 61595
304        18   [1,1,  13]  . . . . >: SEQUENCE OF
305        20   [1,1,   9]  . . . . . . >: OBJECT IDENTIFIER 1.2.840.113549.1.1.5
306        31   [1,1,   0]  . . . . . . >: NULL
307        33   [1,3, 274]  . . . . >: SEQUENCE OF
308        37   [1,1,  11]  . . . . . . >: SET OF
309        39   [1,1,   9]  . . . . . . . . >: SEQUENCE OF
310        41   [1,1,   3]  . . . . . . . . . . >: OBJECT IDENTIFIER 2.5.4.6
311        46   [1,1,   2]  . . . . . . . . . . >: PrintableString PrintableString ES
312     [...]
313      1409   [1,1,  50]  . . . . . . >: SEQUENCE OF
314      1411   [1,1,   8]  . . . . . . . . >: OBJECT IDENTIFIER 1.3.6.1.5.5.7.1.1
315      1421   [1,1,  38]  . . . . . . . . >: OCTET STRING 38 bytes
316                         . . . . . . . . . 30:24:30:22:06:08:2B:06:01:05:05:07:30:01:86:16
317                         . . . . . . . . . 68:74:74:70:3A:2F:2F:6F:63:73:70:2E:69:70:73:63
318                         . . . . . . . . . 61:2E:63:6F:6D:2F
319      1461   [1,1,  13]  . . >: SEQUENCE OF
320      1463   [1,1,   9]  . . . . >: OBJECT IDENTIFIER 1.2.840.113549.1.1.5
321      1474   [1,1,   0]  . . . . >: NULL
322      1476   [1,2, 129]  . . >: BIT STRING 1024 bits
323                         . . . 68:EE:79:97:97:DD:3B:EF:16:6A:06:F2:14:9A:6E:CD
324                         . . . 9E:12:F7:AA:83:10:BD:D1:7C:98:FA:C7:AE:D4:0E:2C
325     [...]
326
327 Human readable OIDs
328 ___________________
329
330 If you have got dictionaries with ObjectIdentifiers, like example one
331 from ``tests/test_crts.py``::
332
333     some_oids = {
334         "1.2.840.113549.1.1.1": "id-rsaEncryption",
335         "1.2.840.113549.1.1.5": "id-sha1WithRSAEncryption",
336         [...]
337         "2.5.4.10": "id-at-organizationName",
338         "2.5.4.11": "id-at-organizationalUnitName",
339     }
340
341 then you can pass it to pretty printer to see human readable OIDs::
342
343     % python -m pyderasn --oids tests.test_crts:some_oids path/to/file
344     [...]
345        37   [1,1,  11]  . . . . . . >: SET OF
346        39   [1,1,   9]  . . . . . . . . >: SEQUENCE OF
347        41   [1,1,   3]  . . . . . . . . . . >: OBJECT IDENTIFIER id-at-countryName (2.5.4.6)
348        46   [1,1,   2]  . . . . . . . . . . >: PrintableString PrintableString ES
349        50   [1,1,  18]  . . . . . . >: SET OF
350        52   [1,1,  16]  . . . . . . . . >: SEQUENCE OF
351        54   [1,1,   3]  . . . . . . . . . . >: OBJECT IDENTIFIER id-at-stateOrProvinceName (2.5.4.8)
352        59   [1,1,   9]  . . . . . . . . . . >: PrintableString PrintableString Barcelona
353        70   [1,1,  18]  . . . . . . >: SET OF
354        72   [1,1,  16]  . . . . . . . . >: SEQUENCE OF
355        74   [1,1,   3]  . . . . . . . . . . >: OBJECT IDENTIFIER id-at-localityName (2.5.4.7)
356        79   [1,1,   9]  . . . . . . . . . . >: PrintableString PrintableString Barcelona
357     [...]
358
359 Decode paths
360 ____________
361
362 Each decoded element has so-called decode path: sequence of structure
363 names it is passing during the decode process. Each element has its own
364 unique path inside the whole ASN.1 tree. You can print it out with
365 ``--print-decode-path`` option::
366
367     % python -m pyderasn --schema path.to:Certificate --print-decode-path path/to/file
368        0    [1,3,1604]  Certificate SEQUENCE []
369        4    [1,3,1453]   . tbsCertificate: TBSCertificate SEQUENCE [tbsCertificate]
370       10-2  [1,1,   1]   . . version: [0] EXPLICIT Version INTEGER v3 OPTIONAL [tbsCertificate:version]
371       13    [1,1,   3]   . . serialNumber: CertificateSerialNumber INTEGER 61595 [tbsCertificate:serialNumber]
372       18    [1,1,  13]   . . signature: AlgorithmIdentifier SEQUENCE [tbsCertificate:signature]
373       20    [1,1,   9]   . . . algorithm: OBJECT IDENTIFIER 1.2.840.113549.1.1.5 [tbsCertificate:signature:algorithm]
374       31    [0,0,   2]   . . . parameters: [UNIV 5] ANY OPTIONAL [tbsCertificate:signature:parameters]
375                          . . . . 05:00
376       33    [0,0, 278]   . . issuer: Name CHOICE rdnSequence [tbsCertificate:issuer]
377       33    [1,3, 274]   . . . rdnSequence: RDNSequence SEQUENCE OF [tbsCertificate:issuer:rdnSequence]
378       37    [1,1,  11]   . . . . 0: RelativeDistinguishedName SET OF [tbsCertificate:issuer:rdnSequence:0]
379       39    [1,1,   9]   . . . . . 0: AttributeTypeAndValue SEQUENCE [tbsCertificate:issuer:rdnSequence:0:0]
380       41    [1,1,   3]   . . . . . . type: AttributeType OBJECT IDENTIFIER 2.5.4.6 [tbsCertificate:issuer:rdnSequence:0:0:type]
381       46    [0,0,   4]   . . . . . . value: [UNIV 19] AttributeValue ANY [tbsCertificate:issuer:rdnSequence:0:0:value]
382                          . . . . . . . 13:02:45:53
383       46    [1,1,   2]   . . . . . . . DEFINED BY 2.5.4.6: CountryName PrintableString ES [tbsCertificate:issuer:rdnSequence:0:0:value:DEFINED BY 2.5.4.6]
384     [...]
385
386 Now you can print only the specified tree, for example signature algorithm::
387
388     % python -m pyderasn --schema path.to:Certificate --decode-path-only tbsCertificate:signature path/to/file
389       18    [1,1,  13]  AlgorithmIdentifier SEQUENCE
390       20    [1,1,   9]   . algorithm: OBJECT IDENTIFIER 1.2.840.113549.1.1.5
391       31    [0,0,   2]   . parameters: [UNIV 5] ANY OPTIONAL
392                          . . 05:00
393
394 Descriptive errors
395 ------------------
396
397 If you have bad DER/BER, then errors will show you where error occurred::
398
399     % python -m pyderasn --schema tests.test_crts:Certificate path/to/bad/file
400     Traceback (most recent call last):
401     [...]
402     pyderasn.DecodeError: UTCTime (tbsCertificate:validity:notAfter:utcTime) (at 328) invalid UTCTime format
403
404 ::
405
406     % python -m pyderasn path/to/bad/file
407     [...]
408     pyderasn.DecodeError: UTCTime (0:SequenceOf:4:SequenceOf:1:UTCTime) (at 328) invalid UTCTime format
409
410 You can see, so called, decode path inside the structures:
411 ``tbsCertificate`` -> ``validity`` -> ``notAfter`` -> ``utcTime`` and
412 that object at byte 328 is invalid.
413
414 X.509 certificate creation
415 --------------------------
416
417 Let's create some simple self-signed X.509 certificate from the ground::
418
419     tbs = TBSCertificate()
420     tbs["serialNumber"] = CertificateSerialNumber(10143011886257155224)
421
422     sign_algo_id = AlgorithmIdentifier((
423         ("algorithm", ObjectIdentifier("1.2.840.113549.1.1.5")),
424         ("parameters", Any(Null())),
425     ))
426     tbs["signature"] = sign_algo_id
427
428     rdnSeq = RDNSequence()
429     for oid, klass, text in (
430             ("2.5.4.6", PrintableString, "XX"),
431             ("2.5.4.8", PrintableString, "Some-State"),
432             ("2.5.4.7", PrintableString, "City"),
433             ("2.5.4.10", PrintableString, "Internet Widgits Pty Ltd"),
434             ("2.5.4.3", PrintableString, "false.example.com"),
435             ("1.2.840.113549.1.9.1", IA5String, "false@example.com"),
436     ):
437         rdnSeq.append(
438             RelativeDistinguishedName((
439                 AttributeTypeAndValue((
440                     ("type", AttributeType(oid)),
441                     ("value", AttributeValue(klass(text))),
442                 )),
443             ))
444         )
445     issuer = Name(("rdnSequence", rdnSeq))
446     tbs["issuer"] = issuer
447     tbs["subject"] = issuer
448
449     validity = Validity((
450         ("notBefore", Time(
451             ("utcTime", UTCTime(datetime(2009, 10, 8, 0, 25, 53))),
452         )),
453         ("notAfter", Time(
454             ("utcTime", UTCTime(datetime(2010, 10, 8, 0, 25, 53))),
455         )),
456     ))
457     tbs["validity"] = validity
458
459     spki = SubjectPublicKeyInfo()
460     spki_algo_id = sign_algo_id.copy()
461     spki_algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.1")
462     spki["algorithm"] = spki_algo_id
463     spki["subjectPublicKey"] = BitString(hexdec("".join((
464         "3048024100cdb7639c3278f006aa277f6eaf42902b592d8cbcbe38a1c92ba4695",
465         "a331b1deadeadd8e9a5c27e8c4c2fd0a8889657722a4f2af7589cf2c77045dc8f",
466         "deec357d0203010001",
467     ))))
468     tbs["subjectPublicKeyInfo"] = spki
469
470     crt = Certificate()
471     crt["tbsCertificate"] = tbs
472     crt["signatureAlgorithm"] = sign_algo_id
473     crt["signatureValue"] = BitString(hexdec("".join((
474         "a67b06ec5ece92772ca413cba3ca12568fdc6c7b4511cd40a7f659980402df2b",
475         "998bb9a4a8cbeb34c0f0a78cf8d91ede14a5ed76bf116fe360aafa8821490435",
476     ))))
477     crt.encode()
478
479 And we will get the same certificate used in Go's library tests.
480
481 DEFINED BY fields
482 -----------------
483
484 Here is only very simple example how you can define Any/OctetString
485 fields automatic decoding::
486
487     class AttributeTypeAndValue(Sequence):
488         schema = (
489             ((("type",), AttributeType(defines=((("value",), {
490                 id_at_countryName: PrintableString(),
491                 id_at_stateOrProvinceName: PrintableString(),
492                 id_at_localityName: PrintableString(),
493                 id_at_organizationName: PrintableString(),
494                 id_at_commonName: PrintableString(),
495             }),)))),
496             ("value", AttributeValue()),
497         )
498
499 And when you will try to decode X.509 certificate with it, your pretty
500 printer will show::
501
502        34   [0,0, 149]  . . issuer: Name CHOICE rdnSequence
503        34   [1,2, 146]  . . . rdnSequence: RDNSequence SEQUENCE OF
504        37   [1,1,  11]  . . . . 0: RelativeDistinguishedName SET OF
505        39   [1,1,   9]  . . . . . 0: AttributeTypeAndValue SEQUENCE
506        41   [1,1,   3]  . . . . . . type: AttributeType OBJECT IDENTIFIER id-at-countryName (2.5.4.6)
507        46   [0,0,   4]  . . . . . . value: [UNIV 19] AttributeValue ANY
508                         . . . . . . . 13:02:58:58
509        46   [1,1,   2]  . . . . . . . DEFINED BY (2.5.4.6): PrintableString PrintableString XX
510        50   [1,1,  19]  . . . . 1: RelativeDistinguishedName SET OF
511        52   [1,1,  17]  . . . . . 0: AttributeTypeAndValue SEQUENCE
512        54   [1,1,   3]  . . . . . . type: AttributeType OBJECT IDENTIFIER id-at-stateOrProvinceName (2.5.4.8)
513        59   [0,0,  12]  . . . . . . value: [UNIV 19] AttributeValue ANY
514                         . . . . . . . 13:0A:53:6F:6D:65:2D:53:74:61:74:65
515        59   [1,1,  10]  . . . . . . . DEFINED BY (2.5.4.8): PrintableString PrintableString Some-State
516        71   [1,1,  13]  . . . . 2: RelativeDistinguishedName SET OF
517        73   [1,1,  11]  . . . . . 0: AttributeTypeAndValue SEQUENCE
518        75   [1,1,   3]  . . . . . . type: AttributeType OBJECT IDENTIFIER id-at-localityName (2.5.4.7)
519        80   [0,0,   6]  . . . . . . value: [UNIV 19] AttributeValue ANY
520                         . . . . . . . 13:04:43:69:74:79
521        80   [1,1,   4]  . . . . . . . DEFINED BY (2.5.4.7): PrintableString PrintableString City
522        86   [1,1,  33]  . . . . 3: RelativeDistinguishedName SET OF
523        88   [1,1,  31]  . . . . . 0: AttributeTypeAndValue SEQUENCE
524        90   [1,1,   3]  . . . . . . type: AttributeType OBJECT IDENTIFIER id-at-organizationName (2.5.4.10)
525        95   [0,0,  26]  . . . . . . value: [UNIV 19] AttributeValue ANY
526                         . . . . . . . 13:18:49:6E:74:65:72:6E:65:74:20:57:69:64:67:69
527                         . . . . . . . 74:73:20:50:74:79:20:4C:74:64
528        95   [1,1,  24]  . . . . . . . DEFINED BY (2.5.4.10): PrintableString PrintableString Internet Widgits Pty Ltd
529
530 :ref:`Read more <definedby>` about that feature.