• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# coding: utf-8
2from __future__ import unicode_literals, division, absolute_import, print_function
3
4import unittest
5import os
6import zlib
7import sys
8from datetime import datetime
9
10from asn1crypto import cms, util
11from ._unittest_compat import patch
12
13patch()
14
15if sys.version_info < (3,):
16    byte_cls = str
17else:
18    byte_cls = bytes
19
20tests_root = os.path.dirname(__file__)
21fixtures_dir = os.path.join(tests_root, 'fixtures')
22
23
24class ClearanceTests(unittest.TestCase):
25
26    def test_clearance_decode_bad_tagging(self):
27        rfc_3281_wrong_tagging = b'\x30\x08\x80\x02\x88\x37\x81\x02\x02\x4c'
28        # This test documents the fact that we can't deal with the "wrong"
29        # version of Clearance in RFC 3281
30        self.assertRaises(
31            ValueError,
32            lambda: cms.Clearance.load(rfc_3281_wrong_tagging).native
33        )
34
35    def test_clearance_decode_correct_tagging(self):
36        correct_tagging = b'\x30\x08\x06\x02\x88\x37\x03\x02\x02\x4c'
37        clearance_obj = cms.Clearance.load(correct_tagging)
38        self.assertEqual(
39            util.OrderedDict([
40                ('policy_id', '2.999'),
41                ('class_list', set(['secret', 'top_secret', 'unclassified'])),
42                ('security_categories', None)
43            ]),
44            clearance_obj.native
45        )
46
47
48class CMSTests(unittest.TestCase):
49
50    def test_create_content_info_data(self):
51        data = cms.SignedData({
52            'version': 'v1',
53            'encap_content_info': {
54                'content_type': 'data',
55                'content': b'Hello',
56            }
57        })
58        info = data['encap_content_info']
59
60        self.assertEqual('v1', data['version'].native)
61        self.assertEqual(
62            'data',
63            info['content_type'].native
64        )
65        self.assertEqual(
66            b'Hello',
67            info['content'].native
68        )
69        self.assertIsInstance(info, cms.ContentInfo)
70
71    def test_create_content_info_data_v2(self):
72        data = cms.SignedData({
73            'version': 'v2',
74            'encap_content_info': {
75                'content_type': 'data',
76                'content': b'Hello',
77            }
78        })
79        info = data['encap_content_info']
80
81        self.assertEqual('v2', data['version'].native)
82        self.assertEqual(
83            'data',
84            info['content_type'].native
85        )
86        self.assertEqual(
87            b'Hello',
88            info['content'].native
89        )
90        self.assertIsInstance(info, cms.EncapsulatedContentInfo)
91
92    def test_parse_content_info_data(self):
93        with open(os.path.join(fixtures_dir, 'message.der'), 'rb') as f:
94            info = cms.ContentInfo.load(f.read())
95
96        self.assertEqual(
97            'data',
98            info['content_type'].native
99        )
100        self.assertEqual(
101            b'This is the message to encapsulate in PKCS#7/CMS\r\n',
102            info['content'].native
103        )
104
105    def test_parse_content_info_compressed_data(self):
106        with open(os.path.join(fixtures_dir, 'cms-compressed.der'), 'rb') as f:
107            info = cms.ContentInfo.load(f.read())
108
109        compressed_data = info['content']
110
111        self.assertEqual(
112            'compressed_data',
113            info['content_type'].native
114        )
115        self.assertEqual(
116            'v0',
117            compressed_data['version'].native
118        )
119        self.assertEqual(
120            'zlib',
121            compressed_data['compression_algorithm']['algorithm'].native
122        )
123        self.assertEqual(
124            None,
125            compressed_data['compression_algorithm']['parameters'].native
126        )
127        self.assertEqual(
128            'data',
129            compressed_data['encap_content_info']['content_type'].native
130        )
131        self.assertEqual(
132            b'\x78\x9C\x0B\xC9\xC8\x2C\x56\x00\xA2\x92\x8C\x54\x85\xDC\xD4\xE2\xE2\xC4\xF4\x54\x85\x92\x7C\x85\xD4\xBC'
133            b'\xE4\xC4\x82\xE2\xD2\x9C\xC4\x92\x54\x85\xCC\x3C\x85\x00\x6F\xE7\x60\x65\x73\x7D\x67\xDF\x60\x2E\x00\xB5'
134            b'\xCF\x10\x71',
135            compressed_data['encap_content_info']['content'].native
136        )
137        self.assertEqual(
138            b'This is the message to encapsulate in PKCS#7/CMS\n',
139            compressed_data.decompressed
140        )
141
142    def test_parse_content_info_indefinite(self):
143        with open(os.path.join(fixtures_dir, 'meca2_compressed.der'), 'rb') as f:
144            info = cms.ContentInfo.load(f.read())
145
146        compressed_data = info['content']
147
148        self.assertEqual(
149            'compressed_data',
150            info['content_type'].native
151        )
152        self.assertEqual(
153            'v0',
154            compressed_data['version'].native
155        )
156        self.assertEqual(
157            'zlib',
158            compressed_data['compression_algorithm']['algorithm'].native
159        )
160        self.assertEqual(
161            None,
162            compressed_data['compression_algorithm']['parameters'].native
163        )
164        self.assertEqual(
165            'data',
166            compressed_data['encap_content_info']['content_type'].native
167        )
168        data = compressed_data['encap_content_info']['content'].native
169        self.assertIsInstance(zlib.decompress(data), byte_cls)
170
171    def test_parse_content_info_digested_data(self):
172        with open(os.path.join(fixtures_dir, 'cms-digested.der'), 'rb') as f:
173            info = cms.ContentInfo.load(f.read())
174
175        digested_data = info['content']
176
177        self.assertEqual(
178            'digested_data',
179            info['content_type'].native
180        )
181        self.assertEqual(
182            'v0',
183            digested_data['version'].native
184        )
185        self.assertEqual(
186            'sha1',
187            digested_data['digest_algorithm']['algorithm'].native
188        )
189        self.assertEqual(
190            None,
191            digested_data['digest_algorithm']['parameters'].native
192        )
193        self.assertEqual(
194            'data',
195            digested_data['encap_content_info']['content_type'].native
196        )
197        self.assertEqual(
198            b'This is the message to encapsulate in PKCS#7/CMS\n',
199            digested_data['encap_content_info']['content'].native
200        )
201        self.assertEqual(
202            b'\x53\xC9\xDB\xC1\x6D\xDB\x34\x3B\x28\x4E\xEF\xA6\x03\x0E\x02\x64\x79\x31\xAF\xFB',
203            digested_data['digest'].native
204        )
205
206    def test_parse_content_info_encrypted_data(self):
207        with open(os.path.join(fixtures_dir, 'cms-encrypted.der'), 'rb') as f:
208            info = cms.ContentInfo.load(f.read())
209
210        encrypted_data = info['content']
211        encrypted_content_info = encrypted_data['encrypted_content_info']
212
213        self.assertEqual(
214            'encrypted_data',
215            info['content_type'].native
216        )
217        self.assertEqual(
218            'v0',
219            encrypted_data['version'].native
220        )
221        self.assertEqual(
222            'data',
223            encrypted_content_info['content_type'].native
224        )
225        self.assertEqual(
226            'aes128_cbc',
227            encrypted_content_info['content_encryption_algorithm']['algorithm'].native
228        )
229        self.assertEqual(
230            'aes',
231            encrypted_content_info['content_encryption_algorithm'].encryption_cipher
232        )
233        self.assertEqual(
234            'cbc',
235            encrypted_content_info['content_encryption_algorithm'].encryption_mode
236        )
237        self.assertEqual(
238            16,
239            encrypted_content_info['content_encryption_algorithm'].key_length
240        )
241        self.assertEqual(
242            16,
243            encrypted_content_info['content_encryption_algorithm'].encryption_block_size
244        )
245        self.assertEqual(
246            b'\x1F\x34\x54\x9F\x7F\xB7\x06\xBD\x81\x57\x68\x84\x79\xB5\x2F\x6F',
247            encrypted_content_info['content_encryption_algorithm']['parameters'].native
248        )
249        self.assertEqual(
250            b'\x80\xEE\x34\x8B\xFC\x04\x69\x4F\xBE\x15\x1C\x0C\x39\x2E\xF3\xEA\x8E\xEE\x17\x0D\x39\xC7\x4B\x6C\x4B'
251            b'\x13\xEF\x17\x82\x0D\xED\xBA\x6D\x2F\x3B\xAB\x4E\xEB\xF0\xDB\xD9\x6E\x1C\xC2\x3C\x1C\x4C\xFA\xF3\x98'
252            b'\x9B\x89\xBD\x48\x77\x07\xE2\x6B\x71\xCF\xB7\xFF\xCE\xA5',
253            encrypted_content_info['encrypted_content'].native
254        )
255
256    def test_parse_content_info_enveloped_data(self):
257        with open(os.path.join(fixtures_dir, 'cms-enveloped.der'), 'rb') as f:
258            info = cms.ContentInfo.load(f.read())
259
260        enveloped_data = info['content']
261        encrypted_content_info = enveloped_data['encrypted_content_info']
262        recipient = enveloped_data['recipient_infos'][0].chosen
263
264        self.assertEqual(
265            'enveloped_data',
266            info['content_type'].native
267        )
268        self.assertEqual(
269            'v0',
270            enveloped_data['version'].native
271        )
272        self.assertEqual(
273            None,
274            enveloped_data['originator_info'].native
275        )
276        self.assertEqual(
277            1,
278            len(enveloped_data['recipient_infos'])
279        )
280        self.assertEqual(
281            'v0',
282            recipient['version'].native
283        )
284        self.assertEqual(
285            util.OrderedDict([
286                (
287                    'issuer',
288                    util.OrderedDict([
289                        ('country_name', 'US'),
290                        ('state_or_province_name', 'Massachusetts'),
291                        ('locality_name', 'Newbury'),
292                        ('organization_name', 'Codex Non Sufficit LC'),
293                        ('organizational_unit_name', 'Testing'),
294                        ('common_name', 'Will Bond'),
295                        ('email_address', 'will@codexns.io'),
296                    ])
297                ),
298                (
299                    'serial_number',
300                    13683582341504654466
301                )
302            ]),
303            recipient['rid'].native
304        )
305        self.assertEqual(
306            'rsaes_pkcs1v15',
307            recipient['key_encryption_algorithm']['algorithm'].native
308        )
309        self.assertEqual(
310            None,
311            recipient['key_encryption_algorithm']['parameters'].native
312        )
313        self.assertEqual(
314            b'\x97\x0A\xFD\x3B\x5C\x27\x45\x69\xCC\xDD\x45\x9E\xA7\x3C\x07\x27\x35\x16\x20\x21\xE4\x6E\x1D\xF8'
315            b'\x5B\xE8\x7F\xD8\x40\x41\xE9\xF2\x92\xCD\xC8\xC5\x03\x95\xEC\x6C\x0B\x97\x71\x87\x86\x3C\xEB\x68'
316            b'\x84\x06\x4E\xE6\xD0\xC4\x7D\x32\xFE\xA6\x06\xC9\xD5\xE1\x8B\xDA\xBF\x96\x5C\x20\x15\x49\x64\x7A'
317            b'\xA2\x4C\xFF\x8B\x0D\xEA\x76\x35\x9B\x7C\x43\xF7\x21\x95\x26\xE7\x70\x30\x98\x5F\x0D\x5E\x4A\xCB'
318            b'\xAD\x47\xDF\x46\xDA\x1F\x0E\xE2\xFE\x3A\x40\xD9\xF2\xDC\x0C\x97\xD9\x91\xED\x34\x8D\xF3\x73\xB0'
319            b'\x90\xF9\xDD\x31\x4D\x37\x93\x81\xD3\x92\xCB\x72\x4A\xD6\x9D\x01\x82\x85\xD5\x1F\xE2\xAA\x32\x12'
320            b'\x82\x4E\x17\xF6\xAA\x58\xDE\xBD\x1B\x80\xAF\x61\xF1\x8A\xD1\x7F\x9D\x41\x6A\xC0\xE4\xC7\x7E\x17'
321            b'\xDC\x94\x33\xE9\x74\x7E\xE9\xF8\x5C\x30\x87\x9B\xD6\xF0\xE3\x4A\xB7\xE3\xCC\x51\x8A\xD4\x37\xF1'
322            b'\xF9\x33\xB5\xD6\x1F\x36\xC1\x6F\x91\xA8\x5F\xE2\x6B\x08\xC7\x9D\xE8\xFD\xDC\xE8\x78\xE0\xC0\xC7'
323            b'\xCF\xC5\xEE\x60\xEC\x54\xFF\x1A\x9C\xF7\x4E\x2C\xD0\x88\xDC\xC2\x1F\xDC\x8A\x37\x9B\x71\x20\xFF'
324            b'\xFD\x6C\xE5\xBA\x8C\xDF\x0E\x3F\x20\xC6\xCB\x08\xA7\x07\xDB\x83',
325            recipient['encrypted_key'].native
326        )
327        self.assertEqual(
328            'data',
329            encrypted_content_info['content_type'].native
330        )
331        self.assertEqual(
332            'tripledes_3key',
333            encrypted_content_info['content_encryption_algorithm']['algorithm'].native
334        )
335        self.assertEqual(
336            'tripledes',
337            encrypted_content_info['content_encryption_algorithm'].encryption_cipher
338        )
339        self.assertEqual(
340            'cbc',
341            encrypted_content_info['content_encryption_algorithm'].encryption_mode
342        )
343        self.assertEqual(
344            24,
345            encrypted_content_info['content_encryption_algorithm'].key_length
346        )
347        self.assertEqual(
348            8,
349            encrypted_content_info['content_encryption_algorithm'].encryption_block_size
350        )
351        self.assertEqual(
352            b'\x52\x50\x98\xFA\x33\x88\xC7\x3C',
353            encrypted_content_info['content_encryption_algorithm']['parameters'].native
354        )
355        self.assertEqual(
356            b'\xDC\x88\x55\x08\xE5\x67\x70\x49\x99\x54\xFD\xF8\x40\x7C\x38\xD5\x78\x1D\x6A\x95\x6D\x1E\xC4\x12'
357            b'\x39\xFE\xC0\x76\xDC\xF5\x79\x1A\x69\xA1\xB9\x40\x1E\xCF\xC8\x79\x3E\xF3\x38\xB4\x90\x00\x27\xD1'
358            b'\xB5\x64\xAB\x99\x51\x13\xF1\x0A',
359            encrypted_content_info['encrypted_content'].native
360        )
361        self.assertEqual(
362            None,
363            enveloped_data['unprotected_attrs'].native
364        )
365
366    def test_parse_content_info_cms_signed_data(self):
367        with open(os.path.join(fixtures_dir, 'cms-signed.der'), 'rb') as f:
368            info = cms.ContentInfo.load(f.read())
369
370        signed_data = info['content']
371        encap_content_info = signed_data['encap_content_info']
372
373        self.assertEqual(
374            'signed_data',
375            info['content_type'].native
376        )
377        self.assertEqual(
378            'v1',
379            signed_data['version'].native
380        )
381        self.assertEqual(
382            [
383                util.OrderedDict([
384                    ('algorithm', 'sha256'),
385                    ('parameters', None),
386                ])
387            ],
388            signed_data['digest_algorithms'].native
389        )
390        self.assertEqual(
391            'data',
392            encap_content_info['content_type'].native
393        )
394        self.assertEqual(
395            b'This is the message to encapsulate in PKCS#7/CMS\r\n',
396            encap_content_info['content'].native
397        )
398
399        self.assertEqual(
400            1,
401            len(signed_data['certificates'])
402        )
403        certificate = signed_data['certificates'][0]
404        with open(os.path.join(fixtures_dir, 'keys/test-der.crt'), 'rb') as f:
405            self.assertEqual(
406                f.read(),
407                certificate.dump()
408            )
409
410        self.assertEqual(
411            1,
412            len(signed_data['signer_infos'])
413        )
414        signer = signed_data['signer_infos'][0]
415
416        self.assertEqual(
417            'v1',
418            signer['version'].native
419        )
420        self.assertEqual(
421            util.OrderedDict([
422                (
423                    'issuer',
424                    util.OrderedDict([
425                        ('country_name', 'US'),
426                        ('state_or_province_name', 'Massachusetts'),
427                        ('locality_name', 'Newbury'),
428                        ('organization_name', 'Codex Non Sufficit LC'),
429                        ('organizational_unit_name', 'Testing'),
430                        ('common_name', 'Will Bond'),
431                        ('email_address', 'will@codexns.io'),
432                    ])
433                ),
434                (
435                    'serial_number',
436                    13683582341504654466
437                )
438            ]),
439            signer['sid'].native
440        )
441        self.assertEqual(
442            util.OrderedDict([
443                ('algorithm', 'sha256'),
444                ('parameters', None),
445            ]),
446            signer['digest_algorithm'].native
447        )
448
449        signed_attrs = signer['signed_attrs']
450
451        self.assertEqual(
452            3,
453            len(signed_attrs)
454        )
455        self.assertEqual(
456            'content_type',
457            signed_attrs[0]['type'].native
458        )
459        self.assertEqual(
460            'data',
461            signed_attrs[0]['values'][0].native
462        )
463        self.assertEqual(
464            'signing_time',
465            signed_attrs[1]['type'].native
466        )
467        self.assertEqual(
468            datetime(2015, 5, 30, 13, 12, 38, tzinfo=util.timezone.utc),
469            signed_attrs[1]['values'][0].native
470        )
471        self.assertEqual(
472            'message_digest',
473            signed_attrs[2]['type'].native
474        )
475        self.assertEqual(
476            b'\xA1\x30\xE2\x87\x90\x5A\x58\x15\x7A\x44\x54\x7A\xB9\xBC\xAE\xD3\x00\xF3\xEC\x3E\x97\xFF'
477            b'\x03\x20\x79\x34\x9D\x62\xAA\x20\xA5\x1D',
478            signed_attrs[2]['values'][0].native
479        )
480
481        self.assertEqual(
482            util.OrderedDict([
483                ('algorithm', 'rsassa_pkcs1v15'),
484                ('parameters', None),
485            ]),
486            signer['signature_algorithm'].native
487        )
488        self.assertEqual(
489            b'\xAC\x2F\xE3\x25\x39\x8F\xD3\xDF\x80\x4F\x0D\xBA\xB1\xEE\x99\x09\xA9\x21\xBB\xDF\x3C\x1E'
490            b'\x70\xDA\xDF\xC4\x0F\x1D\x10\x29\xBC\x94\xBE\xF8\xA8\xC2\x2D\x2A\x1F\x14\xBC\x4A\x5B\x66'
491            b'\x7F\x6F\xE4\xDF\x82\x4D\xD9\x3F\xEB\x89\xAA\x05\x1A\xE5\x58\xCE\xC4\x33\x53\x6E\xE4\x66'
492            b'\xF9\x21\xCF\x80\x35\x46\x88\xB5\x6A\xEA\x5C\x54\x49\x40\x31\xD6\xDC\x20\xD8\xA0\x63\x8C'
493            b'\xC1\xC3\xA1\x72\x5D\x0D\xCE\x43\xB1\x5C\xD8\x32\x3F\xA9\xE7\xBB\xD9\x56\xAE\xE7\xFB\x7C'
494            b'\x37\x32\x8B\x93\xC2\xC4\x47\xDD\x00\xFB\x1C\xEF\xC3\x68\x32\xDC\x06\x26\x17\x45\xF5\xB3'
495            b'\xDC\xD8\x5C\x2B\xC1\x8B\x97\x93\xB8\xF1\x85\xE2\x92\x3B\xC4\x6A\x6A\x89\xC5\x14\x51\x4A'
496            b'\x06\x11\x54\xB0\x29\x07\x75\xD8\xDF\x6B\xFB\x21\xE4\xA4\x09\x17\xAF\xAC\xA0\xF5\xC0\xFE'
497            b'\x7B\x03\x04\x40\x41\x57\xC4\xFD\x58\x1D\x10\x5E\xAC\x23\xAB\xAA\x80\x95\x96\x02\x71\x84'
498            b'\x9C\x0A\xBD\x54\xC4\xA2\x47\xAA\xE7\xC3\x09\x13\x6E\x26\x7D\x72\xAA\xA9\x0B\xF3\xCC\xC4'
499            b'\x48\xB4\x97\x14\x00\x47\x2A\x6B\xD3\x93\x3F\xD8\xFD\xAA\xB9\xFB\xFB\xD5\x09\x8D\x82\x8B'
500            b'\xDE\x0F\xED\x39\x6D\x7B\xDC\x76\x8B\xA6\x4E\x9B\x7A\xBA',
501            signer['signature'].native
502        )
503
504    def test_parse_content_info_pkcs7_signed_data(self):
505        with open(os.path.join(fixtures_dir, 'pkcs7-signed.der'), 'rb') as f:
506            info = cms.ContentInfo.load(f.read())
507
508        signed_data = info['content']
509        encap_content_info = signed_data['encap_content_info']
510
511        self.assertEqual(
512            'signed_data',
513            info['content_type'].native
514        )
515        self.assertEqual(
516            'v1',
517            signed_data['version'].native
518        )
519        self.assertEqual(
520            [
521                util.OrderedDict([
522                    ('algorithm', 'sha256'),
523                    ('parameters', None),
524                ])
525            ],
526            signed_data['digest_algorithms'].native
527        )
528        self.assertEqual(
529            'data',
530            encap_content_info['content_type'].native
531        )
532        self.assertEqual(
533            b'This is the message to encapsulate in PKCS#7/CMS\n',
534            encap_content_info['content'].native
535        )
536
537        self.assertEqual(
538            1,
539            len(signed_data['certificates'])
540        )
541        certificate = signed_data['certificates'][0]
542        with open(os.path.join(fixtures_dir, 'keys/test-der.crt'), 'rb') as f:
543            self.assertEqual(
544                f.read(),
545                certificate.dump()
546            )
547
548        self.assertEqual(
549            1,
550            len(signed_data['signer_infos'])
551        )
552        signer = signed_data['signer_infos'][0]
553
554        self.assertEqual(
555            'v1',
556            signer['version'].native
557        )
558        self.assertEqual(
559            util.OrderedDict([
560                (
561                    'issuer',
562                    util.OrderedDict([
563                        ('country_name', 'US'),
564                        ('state_or_province_name', 'Massachusetts'),
565                        ('locality_name', 'Newbury'),
566                        ('organization_name', 'Codex Non Sufficit LC'),
567                        ('organizational_unit_name', 'Testing'),
568                        ('common_name', 'Will Bond'),
569                        ('email_address', 'will@codexns.io'),
570                    ])
571                ),
572                (
573                    'serial_number',
574                    13683582341504654466
575                )
576            ]),
577            signer['sid'].native
578        )
579        self.assertEqual(
580            util.OrderedDict([
581                ('algorithm', 'sha256'),
582                ('parameters', None),
583            ]),
584            signer['digest_algorithm'].native
585        )
586
587        signed_attrs = signer['signed_attrs']
588
589        self.assertEqual(
590            4,
591            len(signed_attrs)
592        )
593        self.assertEqual(
594            'content_type',
595            signed_attrs[0]['type'].native
596        )
597        self.assertEqual(
598            'data',
599            signed_attrs[0]['values'][0].native
600        )
601        self.assertEqual(
602            'signing_time',
603            signed_attrs[1]['type'].native
604        )
605        self.assertEqual(
606            datetime(2015, 6, 3, 5, 55, 12, tzinfo=util.timezone.utc),
607            signed_attrs[1]['values'][0].native
608        )
609        self.assertEqual(
610            'message_digest',
611            signed_attrs[2]['type'].native
612        )
613        self.assertEqual(
614            b'\x52\x88\x25\x47\x15\x5B\x2D\x50\x44\x68\x05\x24\xC8\x71\x5A\xCC\x62\x28\x36\x17\xB7\x68'
615            b'\xEE\xA1\x12\x90\x96\x4F\x94\xAE\xDB\x79',
616            signed_attrs[2]['values'][0].native
617        )
618
619        self.assertEqual(
620            util.OrderedDict([
621                ('algorithm', 'rsassa_pkcs1v15'),
622                ('parameters', None),
623            ]),
624            signer['signature_algorithm'].native
625        )
626        self.assertEqual(
627            b'\x43\x66\xEE\xF4\x6A\x02\x6F\xFE\x0D\xAE\xE6\xF3\x7A\x8F\x2C\x8E\x26\xB6\x25\x68\xEF\x5B'
628            b'\x4B\x4F\x9C\xE4\xE6\x71\x42\x22\xEC\x97\xFC\x53\xD9\xD6\x36\x1F\xA1\x32\x35\xFF\xA9\x95'
629            b'\x45\x50\x36\x36\x0C\x9A\x10\x6F\x06\xB6\x9D\x25\x10\x08\xF5\xF4\xE1\x68\x62\x60\xE5\xBF'
630            b'\xBD\xE2\x9F\xBD\x8A\x10\x29\x3B\xAF\xE7\xD6\x55\x7C\xEE\x3B\xFB\x93\x42\xE0\xB4\x4F\x89'
631            b'\xD0\x7B\x18\x51\x85\x90\x47\xF0\x5E\xE1\x15\x2C\xC1\x9A\xF1\x49\xE8\x11\x29\x17\x2E\x77'
632            b'\xD3\x35\x10\xAA\xCD\x32\x07\x32\x74\xCF\x2D\x89\xBD\xEF\xC7\xC9\xE7\xEC\x90\x44\xCE\x0B'
633            b'\xC5\x97\x00\x26\x67\x8A\x89\x5B\xFA\x46\xB2\x92\xD5\xCB\xA3\x52\x16\xDC\xF0\xF0\x79\xCB'
634            b'\x90\x93\x8E\x26\xB3\xEB\x8F\xBD\x54\x06\xD6\xB0\xA0\x04\x47\x7C\x63\xFC\x88\x5A\xE3\x81'
635            b'\xDF\x1E\x4D\x39\xFD\xF5\xA0\xE2\xD3\xAB\x13\xC1\xCF\x50\xB2\x0B\xC9\x36\xD6\xCB\xEA\x55'
636            b'\x39\x97\x8E\x34\x47\xE3\x6B\x44\x4A\x0E\x03\xAF\x41\xB2\x47\x2E\x26\xA3\x6B\x5F\xA1\x5C'
637            b'\x86\xA1\x96\x37\x02\xD3\x7C\x5F\xC1\xAF\x81\xE4\x1A\xD9\x87\x44\xB5\xB3\x5C\x45\x6C\xFF'
638            b'\x97\x4C\x3A\xB4\x2F\x5C\x2F\x86\x15\x51\x71\xA6\x27\x68',
639            signer['signature'].native
640        )
641
642    def test_parse_cms_signed_date_indefinite_length(self):
643        with open(os.path.join(fixtures_dir, 'cms-signed-indefinite-length.der'), 'rb') as f:
644            info = cms.ContentInfo.load(f.read())
645            signed_data = info['content']
646            self.assertIsInstance(signed_data.native, util.OrderedDict)
647
648    def test_parse_content_info_cms_signed_digested_data(self):
649        with open(os.path.join(fixtures_dir, 'cms-signed-digested.der'), 'rb') as f:
650            info = cms.ContentInfo.load(f.read())
651
652        signed_data = info['content']
653        encap_content_info = signed_data['encap_content_info']
654
655        self.assertEqual(
656            'signed_data',
657            info['content_type'].native
658        )
659        self.assertEqual(
660            'v2',
661            signed_data['version'].native
662        )
663        self.assertEqual(
664            [
665                util.OrderedDict([
666                    ('algorithm', 'sha256'),
667                    ('parameters', None),
668                ])
669            ],
670            signed_data['digest_algorithms'].native
671        )
672        self.assertEqual(
673            'digested_data',
674            encap_content_info['content_type'].native
675        )
676        self.assertEqual(
677            util.OrderedDict([
678                ('version', 'v0'),
679                (
680                    'digest_algorithm',
681                    util.OrderedDict([
682                        ('algorithm', 'sha1'),
683                        ('parameters', None),
684                    ])
685                ),
686                (
687                    'encap_content_info',
688                    util.OrderedDict([
689                        ('content_type', 'data'),
690                        ('content', b'This is the message to encapsulate in PKCS#7/CMS\n'),
691                    ])
692                ),
693                (
694                    'digest',
695                    b'\x53\xC9\xDB\xC1\x6D\xDB\x34\x3B\x28\x4E\xEF\xA6\x03\x0E\x02\x64\x79\x31\xAF\xFB'
696                )
697            ]),
698            encap_content_info['content'].native
699        )
700
701        self.assertEqual(
702            1,
703            len(signed_data['certificates'])
704        )
705        certificate = signed_data['certificates'][0]
706        with open(os.path.join(fixtures_dir, 'keys/test-der.crt'), 'rb') as f:
707            self.assertEqual(
708                f.read(),
709                certificate.dump()
710            )
711
712        self.assertEqual(
713            1,
714            len(signed_data['signer_infos'])
715        )
716        signer = signed_data['signer_infos'][0]
717
718        self.assertEqual(
719            'v1',
720            signer['version'].native
721        )
722        self.assertEqual(
723            util.OrderedDict([
724                (
725                    'issuer',
726                    util.OrderedDict([
727                        ('country_name', 'US'),
728                        ('state_or_province_name', 'Massachusetts'),
729                        ('locality_name', 'Newbury'),
730                        ('organization_name', 'Codex Non Sufficit LC'),
731                        ('organizational_unit_name', 'Testing'),
732                        ('common_name', 'Will Bond'),
733                        ('email_address', 'will@codexns.io'),
734                    ])
735                ),
736                (
737                    'serial_number',
738                    13683582341504654466
739                )
740            ]),
741            signer['sid'].native
742        )
743        self.assertEqual(
744            util.OrderedDict([
745                ('algorithm', 'sha256'),
746                ('parameters', None),
747            ]),
748            signer['digest_algorithm'].native
749        )
750
751        signed_attrs = signer['signed_attrs']
752
753        self.assertEqual(
754            0,
755            len(signed_attrs)
756        )
757
758        self.assertEqual(
759            util.OrderedDict([
760                ('algorithm', 'rsassa_pkcs1v15'),
761                ('parameters', None),
762            ]),
763            signer['signature_algorithm'].native
764        )
765        self.assertEqual(
766            b'\x70\xBC\x18\x82\x41\xD6\xD8\xE7\x5C\xDC\x42\x27\xA5\xA8\xAA\x8B\x16\x15\x61\x3A\xE5\x47'
767            b'\x53\xFD\x8F\x45\xA3\x82\xE2\x72\x44\x07\xD1\xCB\xBF\xB4\x85\x4A\x2A\x16\x19\xDE\xDC\x53'
768            b'\x15\xCF\x98\xEE\x5C\x0E\xDF\xDE\xC8\x79\xCE\x2B\x38\x61\x36\xB0\xA1\xCB\x94\xD6\x4F\xCD'
769            b'\x83\xEF\x0C\xC9\x23\xA0\x7B\x8B\x65\x40\x5C\x3D\xA8\x3E\xCC\x0D\x1F\x17\x23\xF3\x74\x9F'
770            b'\x7E\x88\xF8\xF3\xBE\x4E\x19\x95\x0F\xEB\x95\x55\x69\xB4\xAA\xC3\x2A\x36\x03\x93\x1C\xDC'
771            b'\xE5\x65\x3F\x4E\x5E\x03\xC8\x56\xD8\x57\x8F\xE8\x2D\x85\x32\xDA\xFD\x79\xD4\xDD\x88\xCA'
772            b'\xA3\x14\x41\xE4\x3B\x03\x88\x0E\x2B\x76\xDC\x44\x3D\x4D\xFF\xB2\xC8\xC3\x83\xB1\x33\x37'
773            b'\x53\x51\x33\x4B\xCA\x1A\xAD\x7E\x6A\xBC\x61\x8B\x84\xDB\x7F\xCF\x61\xB2\x1D\x21\x83\xCF'
774            b'\xB8\x3F\xC6\x98\xED\xD8\x66\x06\xCF\x03\x30\x96\x9D\xB4\x7A\x16\xDF\x6E\xA7\x30\xEB\x77'
775            b'\xF7\x40\x13\xFB\xF2\xAC\x41\x79\x9D\xDC\xC0\xED\x4B\x8B\x19\xEE\x05\x3D\x61\x20\x39\x7E'
776            b'\x80\x1D\x3A\x23\x69\x48\x43\x60\x8B\x3E\x63\xAD\x01\x7A\xDE\x6F\x01\xBA\x51\xF3\x4B\x14'
777            b'\xBF\x6B\x77\x1A\x32\xC2\x0C\x93\xCC\x35\xBC\x66\xC6\x69',
778            signer['signature'].native
779        )
780
781    def test_parse_content_info_pkcs7_signed_digested_data(self):
782        with open(os.path.join(fixtures_dir, 'pkcs7-signed-digested.der'), 'rb') as f:
783            info = cms.ContentInfo.load(f.read())
784
785        signed_data = info['content']
786        encap_content_info = signed_data['encap_content_info']
787
788        self.assertEqual(
789            'signed_data',
790            info['content_type'].native
791        )
792        self.assertEqual(
793            'v1',
794            signed_data['version'].native
795        )
796        self.assertEqual(
797            [
798                util.OrderedDict([
799                    ('algorithm', 'sha256'),
800                    ('parameters', None),
801                ])
802            ],
803            signed_data['digest_algorithms'].native
804        )
805        self.assertEqual(
806            'digested_data',
807            encap_content_info['content_type'].native
808        )
809        self.assertEqual(
810            util.OrderedDict([
811                ('version', 'v0'),
812                (
813                    'digest_algorithm',
814                    util.OrderedDict([
815                        ('algorithm', 'sha1'),
816                        ('parameters', None),
817                    ])
818                ),
819                (
820                    'encap_content_info',
821                    util.OrderedDict([
822                        ('content_type', 'data'),
823                        ('content', b'This is the message to encapsulate in PKCS#7/CMS\n'),
824                    ])
825                ),
826                (
827                    'digest',
828                    b'\x53\xC9\xDB\xC1\x6D\xDB\x34\x3B\x28\x4E\xEF\xA6\x03\x0E\x02\x64\x79\x31\xAF\xFB'
829                )
830            ]),
831            encap_content_info['content'].native
832        )
833
834        self.assertEqual(
835            1,
836            len(signed_data['certificates'])
837        )
838        certificate = signed_data['certificates'][0]
839        with open(os.path.join(fixtures_dir, 'keys/test-der.crt'), 'rb') as f:
840            self.assertEqual(
841                f.read(),
842                certificate.dump()
843            )
844
845        self.assertEqual(
846            1,
847            len(signed_data['signer_infos'])
848        )
849        signer = signed_data['signer_infos'][0]
850
851        self.assertEqual(
852            'v1',
853            signer['version'].native
854        )
855        self.assertEqual(
856            util.OrderedDict([
857                (
858                    'issuer',
859                    util.OrderedDict([
860                        ('country_name', 'US'),
861                        ('state_or_province_name', 'Massachusetts'),
862                        ('locality_name', 'Newbury'),
863                        ('organization_name', 'Codex Non Sufficit LC'),
864                        ('organizational_unit_name', 'Testing'),
865                        ('common_name', 'Will Bond'),
866                        ('email_address', 'will@codexns.io'),
867                    ])
868                ),
869                (
870                    'serial_number',
871                    13683582341504654466
872                )
873            ]),
874            signer['sid'].native
875        )
876        self.assertEqual(
877            util.OrderedDict([
878                ('algorithm', 'sha256'),
879                ('parameters', None),
880            ]),
881            signer['digest_algorithm'].native
882        )
883
884        signed_attrs = signer['signed_attrs']
885
886        self.assertEqual(
887            0,
888            len(signed_attrs)
889        )
890
891        self.assertEqual(
892            util.OrderedDict([
893                ('algorithm', 'rsassa_pkcs1v15'),
894                ('parameters', None),
895            ]),
896            signer['signature_algorithm'].native
897        )
898        self.assertEqual(
899            b'\x70\xBC\x18\x82\x41\xD6\xD8\xE7\x5C\xDC\x42\x27\xA5\xA8\xAA\x8B\x16\x15\x61\x3A\xE5\x47'
900            b'\x53\xFD\x8F\x45\xA3\x82\xE2\x72\x44\x07\xD1\xCB\xBF\xB4\x85\x4A\x2A\x16\x19\xDE\xDC\x53'
901            b'\x15\xCF\x98\xEE\x5C\x0E\xDF\xDE\xC8\x79\xCE\x2B\x38\x61\x36\xB0\xA1\xCB\x94\xD6\x4F\xCD'
902            b'\x83\xEF\x0C\xC9\x23\xA0\x7B\x8B\x65\x40\x5C\x3D\xA8\x3E\xCC\x0D\x1F\x17\x23\xF3\x74\x9F'
903            b'\x7E\x88\xF8\xF3\xBE\x4E\x19\x95\x0F\xEB\x95\x55\x69\xB4\xAA\xC3\x2A\x36\x03\x93\x1C\xDC'
904            b'\xE5\x65\x3F\x4E\x5E\x03\xC8\x56\xD8\x57\x8F\xE8\x2D\x85\x32\xDA\xFD\x79\xD4\xDD\x88\xCA'
905            b'\xA3\x14\x41\xE4\x3B\x03\x88\x0E\x2B\x76\xDC\x44\x3D\x4D\xFF\xB2\xC8\xC3\x83\xB1\x33\x37'
906            b'\x53\x51\x33\x4B\xCA\x1A\xAD\x7E\x6A\xBC\x61\x8B\x84\xDB\x7F\xCF\x61\xB2\x1D\x21\x83\xCF'
907            b'\xB8\x3F\xC6\x98\xED\xD8\x66\x06\xCF\x03\x30\x96\x9D\xB4\x7A\x16\xDF\x6E\xA7\x30\xEB\x77'
908            b'\xF7\x40\x13\xFB\xF2\xAC\x41\x79\x9D\xDC\xC0\xED\x4B\x8B\x19\xEE\x05\x3D\x61\x20\x39\x7E'
909            b'\x80\x1D\x3A\x23\x69\x48\x43\x60\x8B\x3E\x63\xAD\x01\x7A\xDE\x6F\x01\xBA\x51\xF3\x4B\x14'
910            b'\xBF\x6B\x77\x1A\x32\xC2\x0C\x93\xCC\x35\xBC\x66\xC6\x69',
911            signer['signature'].native
912        )
913
914    def test_parse_content_info_smime_capabilities(self):
915        with open(os.path.join(fixtures_dir, 'smime-signature-generated-by-thunderbird.p7s'), 'rb') as f:
916            info = cms.ContentInfo.load(f.read())
917
918        signed_attrs = info['content']['signer_infos'][0]['signed_attrs']
919
920        self.assertEqual(
921            'smime_capabilities',
922            signed_attrs[3]['type'].native
923        )
924        smime_capabilities = signed_attrs[3]
925
926        self.assertEqual(
927            1,
928            len(smime_capabilities['values'])
929        )
930        self.assertEqual(
931            7,
932            len(smime_capabilities['values'][0])
933        )
934        self.assertEqual(
935            [capability.native for capability in smime_capabilities['values'][0]],
936            [
937                util.OrderedDict([
938                    ('capability_id', 'aes256_cbc'),
939                    ('parameters', None),
940                ]),
941                util.OrderedDict([
942                    ('capability_id', 'aes128_cbc'),
943                    ('parameters', None),
944                ]),
945                util.OrderedDict([
946                    ('capability_id', 'tripledes_3key'),
947                    ('parameters', None),
948                ]),
949                util.OrderedDict([
950                    ('capability_id', 'rc2'),
951                    ('parameters', 128),
952                ]),
953                util.OrderedDict([
954                    ('capability_id', 'rc2'),
955                    ('parameters', 64),
956                ]),
957                util.OrderedDict([
958                    ('capability_id', 'des'),
959                    ('parameters', None),
960                ]),
961                util.OrderedDict([
962                    ('capability_id', 'rc2'),
963                    ('parameters', 40),
964                ]),
965            ]
966        )
967
968    def test_bad_teletex_inside_pkcs7(self):
969        with open(os.path.join(fixtures_dir, 'mozilla-generated-by-openssl.pkcs7.der'), 'rb') as f:
970            content = cms.ContentInfo.load(f.read())['content']
971        self.assertEqual(
972            util.OrderedDict([
973                ('organizational_unit_name', 'Testing'),
974                ('country_name', 'US'),
975                ('locality_name', 'Mountain View'),
976                ('organization_name', 'Addons Testing'),
977                ('state_or_province_name', 'CA'),
978                ('common_name', '{02b860db-e71f-48d2-a5a0-82072a93d33c}')
979            ]),
980            content['certificates'][0].chosen['tbs_certificate']['subject'].native
981        )
982
983    def test_parse_attribute_cert(self):
984        # regression test for tagging issue in AttCertIssuer
985
986        with open(os.path.join(fixtures_dir, 'example-attr-cert.der'), 'rb') as f:
987            ac_bytes = f.read()
988        ac_parsed = cms.AttributeCertificateV2.load(ac_bytes)
989        self.assertEqual(ac_bytes, ac_parsed.dump(force=True))
990
991        ac_info = ac_parsed['ac_info']
992        self.assertIsInstance(ac_info['issuer'].chosen, cms.V2Form)
993        self.assertEqual(1, len(ac_info['issuer'].chosen['issuer_name']))
994
995    def test_create_role_syntax(self):
996        rs = cms.RoleSyntax({'role_name': {'rfc822_name': 'test@example.com'}})
997        self.assertEqual(
998            util.OrderedDict([
999                ('role_authority', None),
1000                ('role_name', 'test@example.com')
1001            ]),
1002            rs.native
1003        )
1004