asn1.py 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. # -*- coding: ascii -*-
  2. #
  3. # Util/asn1.py : Minimal support for ASN.1 DER binary encoding.
  4. #
  5. # ===================================================================
  6. # The contents of this file are dedicated to the public domain. To
  7. # the extent that dedication to the public domain is not available,
  8. # everyone is granted a worldwide, perpetual, royalty-free,
  9. # non-exclusive license to exercise all rights associated with the
  10. # contents of this file for any purpose whatsoever.
  11. # No rights are reserved.
  12. #
  13. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  15. # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  17. # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  18. # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  19. # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. # SOFTWARE.
  21. # ===================================================================
  22. import struct
  23. from Cryptodome.Util.py3compat import byte_string, b, bchr, bord
  24. from Cryptodome.Util.number import long_to_bytes, bytes_to_long
  25. __all__ = ['DerObject', 'DerInteger', 'DerOctetString', 'DerNull',
  26. 'DerSequence', 'DerObjectId', 'DerBitString', 'DerSetOf']
  27. def _is_number(x, only_non_negative=False):
  28. test = 0
  29. try:
  30. test = x + test
  31. except TypeError:
  32. return False
  33. return not only_non_negative or x >= 0
  34. class BytesIO_EOF(object):
  35. """This class differs from BytesIO in that a ValueError exception is
  36. raised whenever EOF is reached."""
  37. def __init__(self, initial_bytes):
  38. self._buffer = initial_bytes
  39. self._index = 0
  40. self._bookmark = None
  41. def set_bookmark(self):
  42. self._bookmark = self._index
  43. def data_since_bookmark(self):
  44. assert self._bookmark is not None
  45. return self._buffer[self._bookmark:self._index]
  46. def remaining_data(self):
  47. return len(self._buffer) - self._index
  48. def read(self, length):
  49. new_index = self._index + length
  50. if new_index > len(self._buffer):
  51. raise ValueError("Not enough data for DER decoding: expected %d bytes and found %d" % (new_index, len(self._buffer)))
  52. result = self._buffer[self._index:new_index]
  53. self._index = new_index
  54. return result
  55. def read_byte(self):
  56. return bord(self.read(1)[0])
  57. class DerObject(object):
  58. """Base class for defining a single DER object.
  59. This class should never be directly instantiated.
  60. """
  61. def __init__(self, asn1Id=None, payload=b'', implicit=None,
  62. constructed=False, explicit=None):
  63. """Initialize the DER object according to a specific ASN.1 type.
  64. :Parameters:
  65. asn1Id : integer
  66. The universal DER tag number for this object
  67. (e.g. 0x10 for a SEQUENCE).
  68. If None, the tag is not known yet.
  69. payload : byte string
  70. The initial payload of the object (that it,
  71. the content octets).
  72. If not specified, the payload is empty.
  73. implicit : integer
  74. The IMPLICIT tag number to use for the encoded object.
  75. It overrides the universal tag *asn1Id*.
  76. constructed : bool
  77. True when the ASN.1 type is *constructed*.
  78. False when it is *primitive*.
  79. explicit : integer
  80. The EXPLICIT tag number to use for the encoded object.
  81. """
  82. if asn1Id is None:
  83. # The tag octet will be read in with ``decode``
  84. self._tag_octet = None
  85. return
  86. asn1Id = self._convertTag(asn1Id)
  87. self.payload = payload
  88. # In a BER/DER identifier octet:
  89. # * bits 4-0 contain the tag value
  90. # * bit 5 is set if the type is 'constructed'
  91. # and unset if 'primitive'
  92. # * bits 7-6 depend on the encoding class
  93. #
  94. # Class | Bit 7, Bit 6
  95. # ----------------------------------
  96. # universal | 0 0
  97. # application | 0 1
  98. # context-spec | 1 0 (default for IMPLICIT/EXPLICIT)
  99. # private | 1 1
  100. #
  101. if None not in (explicit, implicit):
  102. raise ValueError("Explicit and implicit tags are"
  103. " mutually exclusive")
  104. if implicit is not None:
  105. self._tag_octet = 0x80 | 0x20 * constructed | self._convertTag(implicit)
  106. return
  107. if explicit is not None:
  108. self._tag_octet = 0xA0 | self._convertTag(explicit)
  109. self._inner_tag_octet = 0x20 * constructed | asn1Id
  110. return
  111. self._tag_octet = 0x20 * constructed | asn1Id
  112. def _convertTag(self, tag):
  113. """Check if *tag* is a real DER tag.
  114. Convert it from a character to number if necessary.
  115. """
  116. if not _is_number(tag):
  117. if len(tag) == 1:
  118. tag = bord(tag[0])
  119. # Ensure that tag is a low tag
  120. if not (_is_number(tag) and 0 <= tag < 0x1F):
  121. raise ValueError("Wrong DER tag")
  122. return tag
  123. @staticmethod
  124. def _definite_form(length):
  125. """Build length octets according to BER/DER
  126. definite form.
  127. """
  128. if length > 127:
  129. encoding = long_to_bytes(length)
  130. return bchr(len(encoding) + 128) + encoding
  131. return bchr(length)
  132. def encode(self):
  133. """Return this DER element, fully encoded as a binary byte string."""
  134. # Concatenate identifier octets, length octets,
  135. # and contents octets
  136. output_payload = self.payload
  137. # In case of an EXTERNAL tag, first encode the inner
  138. # element.
  139. if hasattr(self, "_inner_tag_octet"):
  140. output_payload = (bchr(self._inner_tag_octet) +
  141. self._definite_form(len(self.payload)) +
  142. self.payload)
  143. return (bchr(self._tag_octet) +
  144. self._definite_form(len(output_payload)) +
  145. output_payload)
  146. def _decodeLen(self, s):
  147. """Decode DER length octets from a file."""
  148. length = s.read_byte()
  149. if length > 127:
  150. encoded_length = s.read(length & 0x7F)
  151. if bord(encoded_length[0]) == 0:
  152. raise ValueError("Invalid DER: length has leading zero")
  153. length = bytes_to_long(encoded_length)
  154. if length <= 127:
  155. raise ValueError("Invalid DER: length in long form but smaller than 128")
  156. return length
  157. def decode(self, der_encoded, strict=False):
  158. """Decode a complete DER element, and re-initializes this
  159. object with it.
  160. Args:
  161. der_encoded (byte string): A complete DER element.
  162. Raises:
  163. ValueError: in case of parsing errors.
  164. """
  165. if not byte_string(der_encoded):
  166. raise ValueError("Input is not a byte string")
  167. s = BytesIO_EOF(der_encoded)
  168. self._decodeFromStream(s, strict)
  169. # There shouldn't be other bytes left
  170. if s.remaining_data() > 0:
  171. raise ValueError("Unexpected extra data after the DER structure")
  172. return self
  173. def _decodeFromStream(self, s, strict):
  174. """Decode a complete DER element from a file."""
  175. idOctet = s.read_byte()
  176. if self._tag_octet is not None:
  177. if idOctet != self._tag_octet:
  178. raise ValueError("Unexpected DER tag")
  179. else:
  180. self._tag_octet = idOctet
  181. length = self._decodeLen(s)
  182. self.payload = s.read(length)
  183. # In case of an EXTERNAL tag, further decode the inner
  184. # element.
  185. if hasattr(self, "_inner_tag_octet"):
  186. p = BytesIO_EOF(self.payload)
  187. inner_octet = p.read_byte()
  188. if inner_octet != self._inner_tag_octet:
  189. raise ValueError("Unexpected internal DER tag")
  190. length = self._decodeLen(p)
  191. self.payload = p.read(length)
  192. # There shouldn't be other bytes left
  193. if p.remaining_data() > 0:
  194. raise ValueError("Unexpected extra data after the DER structure")
  195. class DerInteger(DerObject):
  196. """Class to model a DER INTEGER.
  197. An example of encoding is::
  198. >>> from Cryptodome.Util.asn1 import DerInteger
  199. >>> from binascii import hexlify, unhexlify
  200. >>> int_der = DerInteger(9)
  201. >>> print hexlify(int_der.encode())
  202. which will show ``020109``, the DER encoding of 9.
  203. And for decoding::
  204. >>> s = unhexlify(b'020109')
  205. >>> try:
  206. >>> int_der = DerInteger()
  207. >>> int_der.decode(s)
  208. >>> print int_der.value
  209. >>> except ValueError:
  210. >>> print "Not a valid DER INTEGER"
  211. the output will be ``9``.
  212. :ivar value: The integer value
  213. :vartype value: integer
  214. """
  215. def __init__(self, value=0, implicit=None, explicit=None):
  216. """Initialize the DER object as an INTEGER.
  217. :Parameters:
  218. value : integer
  219. The value of the integer.
  220. implicit : integer
  221. The IMPLICIT tag to use for the encoded object.
  222. It overrides the universal tag for INTEGER (2).
  223. """
  224. DerObject.__init__(self, 0x02, b'', implicit,
  225. False, explicit)
  226. self.value = value # The integer value
  227. def encode(self):
  228. """Return the DER INTEGER, fully encoded as a
  229. binary string."""
  230. number = self.value
  231. self.payload = b''
  232. while True:
  233. self.payload = bchr(int(number & 255)) + self.payload
  234. if 128 <= number <= 255:
  235. self.payload = bchr(0x00) + self.payload
  236. if -128 <= number <= 255:
  237. break
  238. number >>= 8
  239. return DerObject.encode(self)
  240. def decode(self, der_encoded, strict=False):
  241. """Decode a complete DER INTEGER DER, and re-initializes this
  242. object with it.
  243. Args:
  244. der_encoded (byte string): A complete INTEGER DER element.
  245. Raises:
  246. ValueError: in case of parsing errors.
  247. """
  248. return DerObject.decode(self, der_encoded, strict=strict)
  249. def _decodeFromStream(self, s, strict):
  250. """Decode a complete DER INTEGER from a file."""
  251. # Fill up self.payload
  252. DerObject._decodeFromStream(self, s, strict)
  253. if strict:
  254. if len(self.payload) == 0:
  255. raise ValueError("Invalid encoding for DER INTEGER: empty payload")
  256. if len(self.payload) >= 2 and struct.unpack('>H', self.payload[:2])[0] < 0x80:
  257. raise ValueError("Invalid encoding for DER INTEGER: leading zero")
  258. # Derive self.value from self.payload
  259. self.value = 0
  260. bits = 1
  261. for i in self.payload:
  262. self.value *= 256
  263. self.value += bord(i)
  264. bits <<= 8
  265. if self.payload and bord(self.payload[0]) & 0x80:
  266. self.value -= bits
  267. class DerSequence(DerObject):
  268. """Class to model a DER SEQUENCE.
  269. This object behaves like a dynamic Python sequence.
  270. Sub-elements that are INTEGERs behave like Python integers.
  271. Any other sub-element is a binary string encoded as a complete DER
  272. sub-element (TLV).
  273. An example of encoding is:
  274. >>> from Cryptodome.Util.asn1 import DerSequence, DerInteger
  275. >>> from binascii import hexlify, unhexlify
  276. >>> obj_der = unhexlify('070102')
  277. >>> seq_der = DerSequence([4])
  278. >>> seq_der.append(9)
  279. >>> seq_der.append(obj_der.encode())
  280. >>> print hexlify(seq_der.encode())
  281. which will show ``3009020104020109070102``, the DER encoding of the
  282. sequence containing ``4``, ``9``, and the object with payload ``02``.
  283. For decoding:
  284. >>> s = unhexlify(b'3009020104020109070102')
  285. >>> try:
  286. >>> seq_der = DerSequence()
  287. >>> seq_der.decode(s)
  288. >>> print len(seq_der)
  289. >>> print seq_der[0]
  290. >>> print seq_der[:]
  291. >>> except ValueError:
  292. >>> print "Not a valid DER SEQUENCE"
  293. the output will be::
  294. 3
  295. 4
  296. [4, 9, b'\x07\x01\x02']
  297. """
  298. def __init__(self, startSeq=None, implicit=None):
  299. """Initialize the DER object as a SEQUENCE.
  300. :Parameters:
  301. startSeq : Python sequence
  302. A sequence whose element are either integers or
  303. other DER objects.
  304. implicit : integer
  305. The IMPLICIT tag to use for the encoded object.
  306. It overrides the universal tag for SEQUENCE (16).
  307. """
  308. DerObject.__init__(self, 0x10, b'', implicit, True)
  309. if startSeq is None:
  310. self._seq = []
  311. else:
  312. self._seq = startSeq
  313. # A few methods to make it behave like a python sequence
  314. def __delitem__(self, n):
  315. del self._seq[n]
  316. def __getitem__(self, n):
  317. return self._seq[n]
  318. def __setitem__(self, key, value):
  319. self._seq[key] = value
  320. def __setslice__(self, i, j, sequence):
  321. self._seq[i:j] = sequence
  322. def __delslice__(self, i, j):
  323. del self._seq[i:j]
  324. def __getslice__(self, i, j):
  325. return self._seq[max(0, i):max(0, j)]
  326. def __len__(self):
  327. return len(self._seq)
  328. def __iadd__(self, item):
  329. self._seq.append(item)
  330. return self
  331. def append(self, item):
  332. self._seq.append(item)
  333. return self
  334. def hasInts(self, only_non_negative=True):
  335. """Return the number of items in this sequence that are
  336. integers.
  337. Args:
  338. only_non_negative (boolean):
  339. If ``True``, negative integers are not counted in.
  340. """
  341. items = [x for x in self._seq if _is_number(x, only_non_negative)]
  342. return len(items)
  343. def hasOnlyInts(self, only_non_negative=True):
  344. """Return ``True`` if all items in this sequence are integers
  345. or non-negative integers.
  346. This function returns False is the sequence is empty,
  347. or at least one member is not an integer.
  348. Args:
  349. only_non_negative (boolean):
  350. If ``True``, the presence of negative integers
  351. causes the method to return ``False``."""
  352. return self._seq and self.hasInts(only_non_negative) == len(self._seq)
  353. def encode(self):
  354. """Return this DER SEQUENCE, fully encoded as a
  355. binary string.
  356. Raises:
  357. ValueError: if some elements in the sequence are neither integers
  358. nor byte strings.
  359. """
  360. self.payload = b''
  361. for item in self._seq:
  362. if byte_string(item):
  363. self.payload += item
  364. elif _is_number(item):
  365. self.payload += DerInteger(item).encode()
  366. else:
  367. self.payload += item.encode()
  368. return DerObject.encode(self)
  369. def decode(self, der_encoded, strict=False, nr_elements=None, only_ints_expected=False):
  370. """Decode a complete DER SEQUENCE, and re-initializes this
  371. object with it.
  372. Args:
  373. der_encoded (byte string):
  374. A complete SEQUENCE DER element.
  375. nr_elements (None or integer or list of integers):
  376. The number of members the SEQUENCE can have
  377. only_ints_expected (boolean):
  378. Whether the SEQUENCE is expected to contain only integers.
  379. strict (boolean):
  380. Whether decoding must check for strict DER compliancy.
  381. Raises:
  382. ValueError: in case of parsing errors.
  383. DER INTEGERs are decoded into Python integers. Any other DER
  384. element is not decoded. Its validity is not checked.
  385. """
  386. self._nr_elements = nr_elements
  387. result = DerObject.decode(self, der_encoded, strict=strict)
  388. if only_ints_expected and not self.hasOnlyInts():
  389. raise ValueError("Some members are not INTEGERs")
  390. return result
  391. def _decodeFromStream(self, s, strict):
  392. """Decode a complete DER SEQUENCE from a file."""
  393. self._seq = []
  394. # Fill up self.payload
  395. DerObject._decodeFromStream(self, s, strict)
  396. # Add one item at a time to self.seq, by scanning self.payload
  397. p = BytesIO_EOF(self.payload)
  398. while p.remaining_data() > 0:
  399. p.set_bookmark()
  400. der = DerObject()
  401. der._decodeFromStream(p, strict)
  402. # Parse INTEGERs differently
  403. if der._tag_octet != 0x02:
  404. self._seq.append(p.data_since_bookmark())
  405. else:
  406. derInt = DerInteger()
  407. #import pdb; pdb.set_trace()
  408. data = p.data_since_bookmark()
  409. derInt.decode(data, strict=strict)
  410. self._seq.append(derInt.value)
  411. ok = True
  412. if self._nr_elements is not None:
  413. try:
  414. ok = len(self._seq) in self._nr_elements
  415. except TypeError:
  416. ok = len(self._seq) == self._nr_elements
  417. if not ok:
  418. raise ValueError("Unexpected number of members (%d)"
  419. " in the sequence" % len(self._seq))
  420. class DerOctetString(DerObject):
  421. """Class to model a DER OCTET STRING.
  422. An example of encoding is:
  423. >>> from Cryptodome.Util.asn1 import DerOctetString
  424. >>> from binascii import hexlify, unhexlify
  425. >>> os_der = DerOctetString(b'\\xaa')
  426. >>> os_der.payload += b'\\xbb'
  427. >>> print hexlify(os_der.encode())
  428. which will show ``0402aabb``, the DER encoding for the byte string
  429. ``b'\\xAA\\xBB'``.
  430. For decoding:
  431. >>> s = unhexlify(b'0402aabb')
  432. >>> try:
  433. >>> os_der = DerOctetString()
  434. >>> os_der.decode(s)
  435. >>> print hexlify(os_der.payload)
  436. >>> except ValueError:
  437. >>> print "Not a valid DER OCTET STRING"
  438. the output will be ``aabb``.
  439. :ivar payload: The content of the string
  440. :vartype payload: byte string
  441. """
  442. def __init__(self, value=b'', implicit=None):
  443. """Initialize the DER object as an OCTET STRING.
  444. :Parameters:
  445. value : byte string
  446. The initial payload of the object.
  447. If not specified, the payload is empty.
  448. implicit : integer
  449. The IMPLICIT tag to use for the encoded object.
  450. It overrides the universal tag for OCTET STRING (4).
  451. """
  452. DerObject.__init__(self, 0x04, value, implicit, False)
  453. class DerNull(DerObject):
  454. """Class to model a DER NULL element."""
  455. def __init__(self):
  456. """Initialize the DER object as a NULL."""
  457. DerObject.__init__(self, 0x05, b'', None, False)
  458. class DerObjectId(DerObject):
  459. """Class to model a DER OBJECT ID.
  460. An example of encoding is:
  461. >>> from Cryptodome.Util.asn1 import DerObjectId
  462. >>> from binascii import hexlify, unhexlify
  463. >>> oid_der = DerObjectId("1.2")
  464. >>> oid_der.value += ".840.113549.1.1.1"
  465. >>> print hexlify(oid_der.encode())
  466. which will show ``06092a864886f70d010101``, the DER encoding for the
  467. RSA Object Identifier ``1.2.840.113549.1.1.1``.
  468. For decoding:
  469. >>> s = unhexlify(b'06092a864886f70d010101')
  470. >>> try:
  471. >>> oid_der = DerObjectId()
  472. >>> oid_der.decode(s)
  473. >>> print oid_der.value
  474. >>> except ValueError:
  475. >>> print "Not a valid DER OBJECT ID"
  476. the output will be ``1.2.840.113549.1.1.1``.
  477. :ivar value: The Object ID (OID), a dot separated list of integers
  478. :vartype value: string
  479. """
  480. def __init__(self, value='', implicit=None, explicit=None):
  481. """Initialize the DER object as an OBJECT ID.
  482. :Parameters:
  483. value : string
  484. The initial Object Identifier (e.g. "1.2.0.0.6.2").
  485. implicit : integer
  486. The IMPLICIT tag to use for the encoded object.
  487. It overrides the universal tag for OBJECT ID (6).
  488. explicit : integer
  489. The EXPLICIT tag to use for the encoded object.
  490. """
  491. DerObject.__init__(self, 0x06, b'', implicit, False, explicit)
  492. self.value = value
  493. def encode(self):
  494. """Return the DER OBJECT ID, fully encoded as a
  495. binary string."""
  496. comps = [int(x) for x in self.value.split(".")]
  497. if len(comps) < 2:
  498. raise ValueError("Not a valid Object Identifier string")
  499. self.payload = bchr(40*comps[0]+comps[1])
  500. for v in comps[2:]:
  501. if v == 0:
  502. enc = [0]
  503. else:
  504. enc = []
  505. while v:
  506. enc.insert(0, (v & 0x7F) | 0x80)
  507. v >>= 7
  508. enc[-1] &= 0x7F
  509. self.payload += b''.join([bchr(x) for x in enc])
  510. return DerObject.encode(self)
  511. def decode(self, der_encoded, strict=False):
  512. """Decode a complete DER OBJECT ID, and re-initializes this
  513. object with it.
  514. Args:
  515. der_encoded (byte string):
  516. A complete DER OBJECT ID.
  517. strict (boolean):
  518. Whether decoding must check for strict DER compliancy.
  519. Raises:
  520. ValueError: in case of parsing errors.
  521. """
  522. return DerObject.decode(self, der_encoded, strict)
  523. def _decodeFromStream(self, s, strict):
  524. """Decode a complete DER OBJECT ID from a file."""
  525. # Fill up self.payload
  526. DerObject._decodeFromStream(self, s, strict)
  527. # Derive self.value from self.payload
  528. p = BytesIO_EOF(self.payload)
  529. comps = [str(x) for x in divmod(p.read_byte(), 40)]
  530. v = 0
  531. while p.remaining_data():
  532. c = p.read_byte()
  533. v = v*128 + (c & 0x7F)
  534. if not (c & 0x80):
  535. comps.append(str(v))
  536. v = 0
  537. self.value = '.'.join(comps)
  538. class DerBitString(DerObject):
  539. """Class to model a DER BIT STRING.
  540. An example of encoding is:
  541. >>> from Cryptodome.Util.asn1 import DerBitString
  542. >>> from binascii import hexlify, unhexlify
  543. >>> bs_der = DerBitString(b'\\xaa')
  544. >>> bs_der.value += b'\\xbb'
  545. >>> print hexlify(bs_der.encode())
  546. which will show ``040300aabb``, the DER encoding for the bit string
  547. ``b'\\xAA\\xBB'``.
  548. For decoding:
  549. >>> s = unhexlify(b'040300aabb')
  550. >>> try:
  551. >>> bs_der = DerBitString()
  552. >>> bs_der.decode(s)
  553. >>> print hexlify(bs_der.value)
  554. >>> except ValueError:
  555. >>> print "Not a valid DER BIT STRING"
  556. the output will be ``aabb``.
  557. :ivar value: The content of the string
  558. :vartype value: byte string
  559. """
  560. def __init__(self, value=b'', implicit=None, explicit=None):
  561. """Initialize the DER object as a BIT STRING.
  562. :Parameters:
  563. value : byte string or DER object
  564. The initial, packed bit string.
  565. If not specified, the bit string is empty.
  566. implicit : integer
  567. The IMPLICIT tag to use for the encoded object.
  568. It overrides the universal tag for OCTET STRING (3).
  569. explicit : integer
  570. The EXPLICIT tag to use for the encoded object.
  571. """
  572. DerObject.__init__(self, 0x03, b'', implicit, False, explicit)
  573. # The bitstring value (packed)
  574. if isinstance(value, DerObject):
  575. self.value = value.encode()
  576. else:
  577. self.value = value
  578. def encode(self):
  579. """Return the DER BIT STRING, fully encoded as a
  580. binary string."""
  581. # Add padding count byte
  582. self.payload = b'\x00' + self.value
  583. return DerObject.encode(self)
  584. def decode(self, der_encoded, strict=False):
  585. """Decode a complete DER BIT STRING, and re-initializes this
  586. object with it.
  587. Args:
  588. der_encoded (byte string): a complete DER BIT STRING.
  589. strict (boolean):
  590. Whether decoding must check for strict DER compliancy.
  591. Raises:
  592. ValueError: in case of parsing errors.
  593. """
  594. return DerObject.decode(self, der_encoded, strict)
  595. def _decodeFromStream(self, s, strict):
  596. """Decode a complete DER BIT STRING DER from a file."""
  597. # Fill-up self.payload
  598. DerObject._decodeFromStream(self, s, strict)
  599. if self.payload and bord(self.payload[0]) != 0:
  600. raise ValueError("Not a valid BIT STRING")
  601. # Fill-up self.value
  602. self.value = b''
  603. # Remove padding count byte
  604. if self.payload:
  605. self.value = self.payload[1:]
  606. class DerSetOf(DerObject):
  607. """Class to model a DER SET OF.
  608. An example of encoding is:
  609. >>> from Cryptodome.Util.asn1 import DerBitString
  610. >>> from binascii import hexlify, unhexlify
  611. >>> so_der = DerSetOf([4,5])
  612. >>> so_der.add(6)
  613. >>> print hexlify(so_der.encode())
  614. which will show ``3109020104020105020106``, the DER encoding
  615. of a SET OF with items 4,5, and 6.
  616. For decoding:
  617. >>> s = unhexlify(b'3109020104020105020106')
  618. >>> try:
  619. >>> so_der = DerSetOf()
  620. >>> so_der.decode(s)
  621. >>> print [x for x in so_der]
  622. >>> except ValueError:
  623. >>> print "Not a valid DER SET OF"
  624. the output will be ``[4, 5, 6]``.
  625. """
  626. def __init__(self, startSet=None, implicit=None):
  627. """Initialize the DER object as a SET OF.
  628. :Parameters:
  629. startSet : container
  630. The initial set of integers or DER encoded objects.
  631. implicit : integer
  632. The IMPLICIT tag to use for the encoded object.
  633. It overrides the universal tag for SET OF (17).
  634. """
  635. DerObject.__init__(self, 0x11, b'', implicit, True)
  636. self._seq = []
  637. # All elements must be of the same type (and therefore have the
  638. # same leading octet)
  639. self._elemOctet = None
  640. if startSet:
  641. for e in startSet:
  642. self.add(e)
  643. def __getitem__(self, n):
  644. return self._seq[n]
  645. def __iter__(self):
  646. return iter(self._seq)
  647. def __len__(self):
  648. return len(self._seq)
  649. def add(self, elem):
  650. """Add an element to the set.
  651. Args:
  652. elem (byte string or integer):
  653. An element of the same type of objects already in the set.
  654. It can be an integer or a DER encoded object.
  655. """
  656. if _is_number(elem):
  657. eo = 0x02
  658. elif isinstance(elem, DerObject):
  659. eo = self._tag_octet
  660. else:
  661. eo = bord(elem[0])
  662. if self._elemOctet != eo:
  663. if self._elemOctet is not None:
  664. raise ValueError("New element does not belong to the set")
  665. self._elemOctet = eo
  666. if elem not in self._seq:
  667. self._seq.append(elem)
  668. def decode(self, der_encoded, strict=False):
  669. """Decode a complete SET OF DER element, and re-initializes this
  670. object with it.
  671. DER INTEGERs are decoded into Python integers. Any other DER
  672. element is left undecoded; its validity is not checked.
  673. Args:
  674. der_encoded (byte string): a complete DER BIT SET OF.
  675. strict (boolean):
  676. Whether decoding must check for strict DER compliancy.
  677. Raises:
  678. ValueError: in case of parsing errors.
  679. """
  680. return DerObject.decode(self, der_encoded, strict)
  681. def _decodeFromStream(self, s, strict):
  682. """Decode a complete DER SET OF from a file."""
  683. self._seq = []
  684. # Fill up self.payload
  685. DerObject._decodeFromStream(self, s, strict)
  686. # Add one item at a time to self.seq, by scanning self.payload
  687. p = BytesIO_EOF(self.payload)
  688. setIdOctet = -1
  689. while p.remaining_data() > 0:
  690. p.set_bookmark()
  691. der = DerObject()
  692. der._decodeFromStream(p, strict)
  693. # Verify that all members are of the same type
  694. if setIdOctet < 0:
  695. setIdOctet = der._tag_octet
  696. else:
  697. if setIdOctet != der._tag_octet:
  698. raise ValueError("Not all elements are of the same DER type")
  699. # Parse INTEGERs differently
  700. if setIdOctet != 0x02:
  701. self._seq.append(p.data_since_bookmark())
  702. else:
  703. derInt = DerInteger()
  704. derInt.decode(p.data_since_bookmark(), strict)
  705. self._seq.append(derInt.value)
  706. # end
  707. def encode(self):
  708. """Return this SET OF DER element, fully encoded as a
  709. binary string.
  710. """
  711. # Elements in the set must be ordered in lexicographic order
  712. ordered = []
  713. for item in self._seq:
  714. if _is_number(item):
  715. bys = DerInteger(item).encode()
  716. elif isinstance(item, DerObject):
  717. bys = item.encode()
  718. else:
  719. bys = item
  720. ordered.append(bys)
  721. ordered.sort()
  722. self.payload = b''.join(ordered)
  723. return DerObject.encode(self)