constructed.html 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. <html>
  2. <title>
  3. PyASN1 Constructed types
  4. </title>
  5. <head>
  6. </head>
  7. <body>
  8. <center>
  9. <table width=60%>
  10. <tr>
  11. <td>
  12. <h4>
  13. 1.3 PyASN1 Constructed types
  14. </h4>
  15. <p>
  16. Besides scalar types, ASN.1 specifies so-called constructed ones - these
  17. are capable of holding one or more values of other types, both scalar
  18. and constructed.
  19. </p>
  20. <p>
  21. In pyasn1 implementation, constructed ASN.1 types behave like
  22. Python sequences, and also support additional component addressing methods,
  23. specific to particular constructed type.
  24. </p>
  25. <a name="1.3.1"></a>
  26. <h4>
  27. 1.3.1 Sequence and Set types
  28. </h4>
  29. <p>
  30. The Sequence and Set types have many similar properties:
  31. </p>
  32. <ul>
  33. <li>they can hold any number of inner components of different types
  34. <li>every component has a human-friendly identifier
  35. <li>any component can have a default value
  36. <li>some components can be absent.
  37. </ul>
  38. <p>
  39. However, Sequence type guarantees the ordering of Sequence value components
  40. to match their declaration order. By contrast, components of the
  41. Set type can be ordered to best suite application's needs.
  42. <p>
  43. <table bgcolor="lightgray" border=0 width=100%><TR><TD>
  44. <pre>
  45. Record ::= SEQUENCE {
  46. id INTEGER,
  47. room [0] INTEGER OPTIONAL,
  48. house [1] INTEGER DEFAULT 0
  49. }
  50. </pre>
  51. </td></tr></table>
  52. <p>
  53. Up to this moment, the only method we used for creating new pyasn1 types
  54. is Python sub-classing. With this method, a new, named Python class is created
  55. what mimics type derivation in ASN.1 grammar. However, ASN.1 also allows for
  56. defining anonymous subtypes (room and house components in the example above).
  57. To support anonymous subtyping in pyasn1, a cloning operation on an existing
  58. pyasn1 type object can be invoked what creates a new instance of original
  59. object with possibly modified properties.
  60. </p>
  61. <table bgcolor="lightgray" border=0 width=100%><TR><TD>
  62. <pre>
  63. >>> from pyasn1.type import univ, namedtype, tag
  64. >>> class Record(univ.Sequence):
  65. ... componentType = namedtype.NamedTypes(
  66. ... namedtype.NamedType('id', univ.Integer()),
  67. ... namedtype.OptionalNamedType(
  68. ... 'room',
  69. ... univ.Integer().subtype(
  70. ... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)
  71. ... )
  72. ... ),
  73. ... namedtype.DefaultedNamedType(
  74. ... 'house',
  75. ... univ.Integer(0).subtype(
  76. ... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)
  77. ... )
  78. ... )
  79. ... )
  80. >>>
  81. </pre>
  82. </td></tr></table>
  83. <p>
  84. All pyasn1 constructed type classes have a class attribute <b>componentType</b>
  85. that represent default type specification. Its value is a NamedTypes object.
  86. </p>
  87. <p>
  88. The NamedTypes class instance holds a sequence of NameType, OptionalNamedType
  89. or DefaultedNamedType objects which, in turn, refer to pyasn1 type objects that
  90. represent inner SEQUENCE components specification.
  91. </p>
  92. <p>
  93. Finally, invocation of a subtype() method of pyasn1 type objects in the code
  94. above returns an implicitly tagged copy of original object.
  95. </p>
  96. <p>
  97. Once a SEQUENCE or SET type is decleared with pyasn1, it can be instantiated
  98. and initialized (continuing the above code):
  99. </p>
  100. <table bgcolor="lightgray" border=0 width=100%><TR><TD>
  101. <pre>
  102. >>> record = Record()
  103. >>> record.setComponentByName('id', 123)
  104. >>> print(record.prettyPrint())
  105. Record:
  106. id=123
  107. >>>
  108. >>> record.setComponentByPosition(1, 321)
  109. >>> print(record.prettyPrint())
  110. Record:
  111. id=123
  112. room=321
  113. >>>
  114. >>> record.setDefaultComponents()
  115. >>> print(record.prettyPrint())
  116. Record:
  117. id=123
  118. room=321
  119. house=0
  120. </pre>
  121. </td></tr></table>
  122. <p>
  123. Inner components of pyasn1 Sequence/Set objects could be accessed using the
  124. following methods:
  125. </p>
  126. <table bgcolor="lightgray" border=0 width=100%><TR><TD>
  127. <pre>
  128. >>> record.getComponentByName('id')
  129. Integer(123)
  130. >>> record.getComponentByPosition(1)
  131. Integer(321)
  132. >>> record[2]
  133. Integer(0)
  134. >>> for idx in range(len(record)):
  135. ... print(record.getNameByPosition(idx), record.getComponentByPosition(idx))
  136. id 123
  137. room 321
  138. house 0
  139. >>>
  140. </pre>
  141. </td></tr></table>
  142. <p>
  143. The Set type share all the properties of Sequence type, and additionally
  144. support by-tag component addressing (as all Set components have distinct
  145. types).
  146. </p>
  147. <table bgcolor="lightgray" border=0 width=100%><TR><TD>
  148. <pre>
  149. >>> from pyasn1.type import univ, namedtype, tag
  150. >>> class Gamer(univ.Set):
  151. ... componentType = namedtype.NamedTypes(
  152. ... namedtype.NamedType('score', univ.Integer()),
  153. ... namedtype.NamedType('player', univ.OctetString()),
  154. ... namedtype.NamedType('id', univ.ObjectIdentifier())
  155. ... )
  156. >>> gamer = Gamer()
  157. >>> gamer.setComponentByType(univ.Integer().getTagSet(), 121343)
  158. >>> gamer.setComponentByType(univ.OctetString().getTagSet(), 'Pascal')
  159. >>> gamer.setComponentByType(univ.ObjectIdentifier().getTagSet(), (1,3,7,2))
  160. >>> print(gamer.prettyPrint())
  161. Gamer:
  162. score=121343
  163. player=b'Pascal'
  164. id=1.3.7.2
  165. >>>
  166. </pre>
  167. </td></tr></table>
  168. <a name="1.3.2"></a>
  169. <h4>
  170. 1.3.2 SequenceOf and SetOf types
  171. </h4>
  172. <p>
  173. Both, SequenceOf and SetOf types resemble an unlimited size list of components.
  174. All the components must be of the same type.
  175. </p>
  176. <table bgcolor="lightgray" border=0 width=100%><TR><TD>
  177. <pre>
  178. Progression ::= SEQUENCE OF INTEGER
  179. arithmeticProgression Progression ::= { 1, 3, 5, 7 }
  180. </pre>
  181. </td></tr></table>
  182. <p>
  183. SequenceOf and SetOf types are expressed by the very similar pyasn1 type
  184. objects. Their components can only be addressed by position and they
  185. both have a property of automatic resize.
  186. </p>
  187. <p>
  188. To specify inner component type, the <b>componentType</b> class attribute
  189. should refer to another pyasn1 type object.
  190. </p>
  191. <table bgcolor="lightgray" border=0 width=100%><TR><TD>
  192. <pre>
  193. >>> from pyasn1.type import univ
  194. >>> class Progression(univ.SequenceOf):
  195. ... componentType = univ.Integer()
  196. >>> arithmeticProgression = Progression()
  197. >>> arithmeticProgression.setComponentByPosition(1, 111)
  198. >>> print(arithmeticProgression.prettyPrint())
  199. Progression:
  200. -empty- 111
  201. >>> arithmeticProgression.setComponentByPosition(0, 100)
  202. >>> print(arithmeticProgression.prettyPrint())
  203. Progression:
  204. 100 111
  205. >>>
  206. >>> for idx in range(len(arithmeticProgression)):
  207. ... arithmeticProgression.getComponentByPosition(idx)
  208. Integer(100)
  209. Integer(111)
  210. >>>
  211. </pre>
  212. </td></tr></table>
  213. <p>
  214. Any scalar or constructed pyasn1 type object can serve as an inner component.
  215. Missing components are prohibited in SequenceOf/SetOf value objects.
  216. </p>
  217. <a name="1.3.3"></a>
  218. <h4>
  219. 1.3.3 Choice type
  220. </h4>
  221. <p>
  222. Values of ASN.1 CHOICE type can contain only a single value of a type from a
  223. list of possible alternatives. Alternatives must be ASN.1 types with
  224. distinct tags for the whole structure to remain unambiguous. Unlike most
  225. other types, CHOICE is an untagged one, e.g. it has no base tag of its own.
  226. </p>
  227. <table bgcolor="lightgray" border=0 width=100%><TR><TD>
  228. <pre>
  229. CodeOrMessage ::= CHOICE {
  230. code INTEGER,
  231. message OCTET STRING
  232. }
  233. </pre>
  234. </td></tr></table>
  235. <p>
  236. In pyasn1 implementation, Choice object behaves like Set but accepts only
  237. a single inner component at a time. It also offers a few additional methods
  238. specific to its behaviour.
  239. </p>
  240. <table bgcolor="lightgray" border=0 width=100%><TR><TD>
  241. <pre>
  242. >>> from pyasn1.type import univ, namedtype
  243. >>> class CodeOrMessage(univ.Choice):
  244. ... componentType = namedtype.NamedTypes(
  245. ... namedtype.NamedType('code', univ.Integer()),
  246. ... namedtype.NamedType('message', univ.OctetString())
  247. ... )
  248. >>>
  249. >>> codeOrMessage = CodeOrMessage()
  250. >>> print(codeOrMessage.prettyPrint())
  251. CodeOrMessage:
  252. >>> codeOrMessage.setComponentByName('code', 123)
  253. >>> print(codeOrMessage.prettyPrint())
  254. CodeOrMessage:
  255. code=123
  256. >>> codeOrMessage.setComponentByName('message', 'my string value')
  257. >>> print(codeOrMessage.prettyPrint())
  258. CodeOrMessage:
  259. message=b'my string value'
  260. >>>
  261. </pre>
  262. </td></tr></table>
  263. <p>
  264. Since there could be only a single inner component value in the pyasn1 Choice
  265. value object, either of the following methods could be used for fetching it
  266. (continuing previous code):
  267. </p>
  268. <table bgcolor="lightgray" border=0 width=100%><TR><TD>
  269. <pre>
  270. >>> codeOrMessage.getName()
  271. 'message'
  272. >>> codeOrMessage.getComponent()
  273. OctetString(b'my string value')
  274. >>>
  275. </pre>
  276. </td></tr></table>
  277. <a name="1.3.4"></a>
  278. <h4>
  279. 1.3.4 Any type
  280. </h4>
  281. <p>
  282. The ASN.1 ANY type is a kind of wildcard or placeholder that matches
  283. any other type without knowing it in advance. Like CHOICE type, ANY
  284. has no base tag.
  285. </p>
  286. <table bgcolor="lightgray" border=0 width=100%><TR><TD>
  287. <pre>
  288. Error ::= SEQUENCE {
  289. code INTEGER,
  290. parameter ANY DEFINED BY code
  291. }
  292. </pre>
  293. </td></tr></table>
  294. <p>
  295. The ANY type is frequently used in specifications, where exact type is not
  296. yet agreed upon between communicating parties or the number of possible
  297. alternatives of a type is infinite.
  298. Sometimes an auxiliary selector is kept around to help parties indicate
  299. the kind of ANY payload in effect ("code" in the example above).
  300. </p>
  301. <p>
  302. Values of the ANY type contain serialized ASN.1 value(s) in form of
  303. an octet string. Therefore pyasn1 Any value object share the properties of
  304. pyasn1 OctetString object.
  305. </p>
  306. <table bgcolor="lightgray" border=0 width=100%><TR><TD>
  307. <pre>
  308. >>> from pyasn1.type import univ
  309. >>> someValue = univ.Any(b'\x02\x01\x01')
  310. >>> someValue
  311. Any(b'\x02\x01\x01')
  312. >>> str(someValue)
  313. '\x02\x01\x01'
  314. >>> bytes(someValue)
  315. b'\x02\x01\x01'
  316. >>>
  317. </pre>
  318. </td></tr></table>
  319. <p>
  320. Receiving application is supposed to explicitly deserialize the content of Any
  321. value object, possibly using auxiliary selector for figuring out its ASN.1
  322. type to pick appropriate decoder.
  323. </p>
  324. <p>
  325. There will be some more talk and code snippets covering Any type in the codecs
  326. chapters that follow.
  327. </p>
  328. <hr>
  329. </td>
  330. </tr>
  331. </table>
  332. </center>
  333. </body>
  334. </html>