]> Cypherpunks.ru repositories - pygost.git/blob - pygost/test_cms.py
8eeea91f3edabe6a93eacdfd9d1e0e41c6e31d0e
[pygost.git] / pygost / test_cms.py
1 # coding: utf-8
2 # PyGOST -- Pure Python GOST cryptographic functions library
3 # Copyright (C) 2015-2018 Sergey Matveev <stargrave@stargrave.org>
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18 from base64 import b64decode
19 from unittest import skipIf
20 from unittest import TestCase
21
22 from pygost.gost28147 import cfb_decrypt
23 from pygost.gost3410 import CURVE_PARAMS
24 from pygost.gost3410 import GOST3410Curve
25 from pygost.gost3410 import prv_unmarshal
26 from pygost.gost3410 import pub_unmarshal
27 from pygost.gost3410 import public_key
28 from pygost.gost3410 import verify
29 from pygost.gost3410_vko import kek_34102012256
30 from pygost.gost3410_vko import ukm_unmarshal
31 from pygost.gost34112012256 import GOST34112012256
32 from pygost.gost34112012512 import GOST34112012512
33 from pygost.utils import hexdec
34 from pygost.wrap import unwrap_cryptopro
35 from pygost.wrap import unwrap_gost
36
37 try:
38     from pyderasn import OctetString
39
40     from pygost.asn1schemas.cms import ContentInfo
41     from pygost.asn1schemas.cms import DigestedData
42     from pygost.asn1schemas.cms import EnvelopedData
43     from pygost.asn1schemas.cms import Gost2814789EncryptedKey
44     from pygost.asn1schemas.cms import Gost2814789Parameters
45     from pygost.asn1schemas.cms import GostR3410KeyTransport
46     from pygost.asn1schemas.cms import SignedData
47 except ImportError:
48     pyderasn_exists = False
49 else:
50     pyderasn_exists = True
51
52
53 @skipIf(not pyderasn_exists, "PyDERASN dependency is required")
54 class TestSigned(TestCase):
55     """SignedData test vectors from "Использование
56     алгоритмов ГОСТ 28147-89, ГОСТ Р 34.11 и ГОСТ Р 34.10 в
57     криптографических сообщениях формата CMS" (TK26CMS.pdf)
58     """
59
60     def process_cms(
61             self,
62             content_info_raw,
63             prv_key_raw,
64             curve_name,
65             hasher,
66             mode,
67     ):
68         content_info, tail = ContentInfo().decode(content_info_raw)
69         self.assertSequenceEqual(tail, b"")
70         signed_data, tail = SignedData().decode(bytes(content_info["content"]))
71         self.assertSequenceEqual(tail, b"")
72         self.assertEqual(len(signed_data["signerInfos"]), 1)
73         curve = GOST3410Curve(*CURVE_PARAMS[curve_name])
74         self.assertTrue(verify(
75             curve,
76             public_key(curve, prv_unmarshal(prv_key_raw)),
77             hasher(bytes(signed_data["encapContentInfo"]["eContent"])).digest()[::-1],
78             bytes(signed_data["signerInfos"][0]["signature"]),
79             mode=mode,
80         ))
81
82     def test_256(self):
83         content_info_raw = b64decode("""
84 MIIBBQYJKoZIhvcNAQcCoIH3MIH0AgEBMQ4wDAYIKoUDBwEBAgIFADAbBgkqhkiG
85 9w0BBwGgDgQMVGVzdCBtZXNzYWdlMYHBMIG+AgEBMFswVjEpMCcGCSqGSIb3DQEJ
86 ARYaR29zdFIzNDEwLTIwMTJAZXhhbXBsZS5jb20xKTAnBgNVBAMTIEdvc3RSMzQx
87 MC0yMDEyICgyNTYgYml0KSBleGFtcGxlAgEBMAwGCCqFAwcBAQICBQAwDAYIKoUD
88 BwEBAQEFAARAkptb2ekZbC94FaGDQeP70ExvTkXtOY9zgz3cCco/hxPhXUVo3eCx
89 VNwDQ8enFItJZ8DEX4blZ8QtziNCMl5HbA==
90         """)
91         prv_key_raw = hexdec("BFCF1D623E5CDD3032A7C6EABB4A923C46E43D640FFEAAF2C3ED39A8FA399924")[::-1]
92         self.process_cms(
93             content_info_raw,
94             prv_key_raw,
95             "GostR3410_2001_CryptoPro_XchA_ParamSet",
96             GOST34112012256,
97             2001,
98         )
99
100     def test_512(self):
101         content_info_raw = b64decode("""
102 MIIBSQYJKoZIhvcNAQcCoIIBOjCCATYCAQExDjAMBggqhQMHAQECAwUAMBsGCSqG
103 SIb3DQEHAaAOBAxUZXN0IG1lc3NhZ2UxggECMIH/AgEBMFswVjEpMCcGCSqGSIb3
104 DQEJARYaR29zdFIzNDEwLTIwMTJAZXhhbXBsZS5jb20xKTAnBgNVBAMTIEdvc3RS
105 MzQxMC0yMDEyICg1MTIgYml0KSBleGFtcGxlAgEBMAwGCCqFAwcBAQIDBQAwDAYI
106 KoUDBwEBAQIFAASBgFyVohNhMHUi/+RAF3Gh/cC7why6v+4jPWVlx1TYlXtV8Hje
107 hI2Y+rP52/LO6EUHG/XcwCBbUxmRWsbUSRRBAexmaafkSdvv2FFwC8kHOcti+UPX
108 PS+KRYxT8vhcsBLWWxDkc1McI7aF09hqtED36mQOfACzeJjEoUjALpmJob1V
109         """)
110         prv_key_raw = hexdec("3FC01CDCD4EC5F972EB482774C41E66DB7F380528DFE9E67992BA05AEE462435757530E641077CE587B976C8EEB48C48FD33FD175F0C7DE6A44E014E6BCB074B")[::-1]
111         self.process_cms(
112             content_info_raw,
113             prv_key_raw,
114             "GostR3410_2012_TC26_ParamSetB",
115             GOST34112012512,
116             2012,
117         )
118
119
120 @skipIf(not pyderasn_exists, "PyDERASN dependency is required")
121 class TestDigested(TestCase):
122     """DigestedData test vectors from "Использование
123     алгоритмов ГОСТ 28147-89, ГОСТ Р 34.11 и ГОСТ Р 34.10 в
124     криптографических сообщениях формата CMS" (TK26CMS.pdf)
125     """
126
127     def process_cms(self, content_info_raw, hasher):
128         content_info, tail = ContentInfo().decode(content_info_raw)
129         self.assertSequenceEqual(tail, b"")
130         digested_data, tail = DigestedData().decode(bytes(content_info["content"]))
131         self.assertSequenceEqual(tail, b"")
132         self.assertSequenceEqual(
133             hasher(bytes(digested_data["encapContentInfo"]["eContent"])).digest(),
134             bytes(digested_data["digest"]),
135         )
136
137     def test_256(self):
138         content_info_raw = b64decode("""
139 MIGdBgkqhkiG9w0BBwWggY8wgYwCAQAwDAYIKoUDBwEBAgIFADBXBgkqhkiG9w0B
140 BwGgSgRI0eUg4uXy8OgsINHy8Ojh7uboIOLt8/boLCDi5f7y+iDxIOzu8P8g8fLw
141 5evg7Ogg7eAg9fDg4fD7/yDv6/rq+yDI4+7w5eL7BCCd0v5OkECeXah/U5dtdAWw
142 wMrGKPxmmnQdUAY8VX6PUA==
143         """)
144         self.process_cms(content_info_raw, GOST34112012256)
145
146     def test_512(self):
147         content_info_raw = b64decode("""
148 MIG0BgkqhkiG9w0BBwWggaYwgaMCAQAwDAYIKoUDBwEBAgMFADBOBgkqhkiG9w0B
149 BwGgQQQ/MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAx
150 MjM0NTY3ODkwMTIzNDU2Nzg5MDEyBEAbVNAaSvW51cw9htaNKFRisZq8JHUiLzXA
151 hRIr5Lof+gCtMPh2ezqCOExldPAkwxHipIEzKwjvf0F5eJHBZG9I
152         """)
153         self.process_cms(content_info_raw, GOST34112012512)
154
155
156 @skipIf(not pyderasn_exists, "PyDERASN dependency is required")
157 class TestEnvelopedKTRI(TestCase):
158     """EnvelopedData KeyTransRecipientInfo-based test vectors from
159     "Использование алгоритмов ГОСТ 28147-89, ГОСТ Р 34.11 и ГОСТ Р 34.10
160     в криптографических сообщениях формата CMS" (TK26CMS.pdf)
161     """
162
163     def process_cms(
164             self,
165             content_info_raw,
166             prv_key_our,
167             curve_name,
168             keker,
169             plaintext_expected,
170     ):
171         sbox = "Gost28147_tc26_ParamZ"
172         content_info, tail = ContentInfo().decode(content_info_raw)
173         self.assertSequenceEqual(tail, b"")
174         enveloped_data, tail = EnvelopedData().decode(bytes(content_info["content"]))
175         self.assertSequenceEqual(tail, b"")
176         eci = enveloped_data["encryptedContentInfo"]
177         ri = enveloped_data["recipientInfos"][0]
178         encrypted_key, tail = GostR3410KeyTransport().decode(
179             bytes(ri["ktri"]["encryptedKey"])
180         )
181         self.assertSequenceEqual(tail, b"")
182         ukm = bytes(encrypted_key["transportParameters"]["ukm"])
183         spk = bytes(encrypted_key["transportParameters"]["ephemeralPublicKey"]["subjectPublicKey"])
184         pub_key_their, tail = OctetString().decode(spk)
185         self.assertSequenceEqual(tail, b"")
186         curve = GOST3410Curve(*CURVE_PARAMS[curve_name])
187         kek = keker(curve, prv_key_our, bytes(pub_key_their), ukm)
188         key_wrapped = bytes(encrypted_key["sessionEncryptedKey"]["encryptedKey"])
189         mac = bytes(encrypted_key["sessionEncryptedKey"]["macKey"])
190         cek = unwrap_cryptopro(kek, ukm + key_wrapped + mac, sbox=sbox)
191         ciphertext = bytes(eci["encryptedContent"])
192         encryption_params, tail = Gost2814789Parameters().decode(
193             bytes(eci["contentEncryptionAlgorithm"]["parameters"])
194         )
195         self.assertSequenceEqual(tail, b"")
196         iv = bytes(encryption_params["iv"])
197         self.assertSequenceEqual(
198             cfb_decrypt(cek, ciphertext, iv, sbox=sbox, mesh=True),
199             plaintext_expected,
200         )
201
202     def test_256(self):
203         content_info_raw = b64decode("""
204 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
258         """)
259         prv_key_our = hexdec("BFCF1D623E5CDD3032A7C6EABB4A923C46E43D640FFEAAF2C3ED39A8FA399924")[::-1]
260
261         def keker(curve, prv, pub, ukm):
262             return kek_34102012256(
263                 curve,
264                 prv_unmarshal(prv),
265                 pub_unmarshal(pub),
266                 ukm_unmarshal(ukm),
267                 mode=2001,
268             )
269
270         self.process_cms(
271             content_info_raw,
272             prv_key_our,
273             "GostR3410_2001_CryptoPro_XchA_ParamSet",
274             keker,
275             b"Test data to encrypt.\n" * 100,
276         )
277
278     def test_512(self):
279         content_info_raw = b64decode("""
280 MIIB0gYJKoZIhvcNAQcDoIIBwzCCAb8CAQAxggF8MIIBeAIBADBbMFYxKTAnBgkq
281 hkiG9w0BCQEWGkdvc3RSMzQxMC0yMDEyQGV4YW1wbGUuY29tMSkwJwYDVQQDEyBH
282 b3N0UjM0MTAtMjAxMiA1MTIgYml0cyBleGNoYW5nZQIBATAhBggqhQMHAQEBAjAV
283 BgkqhQMHAQIBAgIGCCqFAwcBAQIDBIHyMIHvMCgEIIsYzbVLn33aLinQ7SLNA7y+
284 Lrm02khqDCfXrNS9iiMhBATerS8zoIHCBgkqhQMHAQIFAQGggaowIQYIKoUDBwEB
285 AQIwFQYJKoUDBwECAQICBggqhQMHAQECAwOBhAAEgYAYiTVLKpSGaAvjJEDQ0hdK
286 qR/jek5Q9Q2pXC+NkOimQh7dpCi+wcaHlPcBk96hmpnOFvLaiokX8V6jqtBl5gdk
287 M40kOXv8kcDdTzEVKA/ZLxA8xanL+gTD6ZjaPsUu06nsA2MoMBWcHLUzueaP3bGT
288 /yHTV+Za5xdcQehag/lNBgQIvCw4uUl0XC4wOgYJKoZIhvcNAQcBMB8GBiqFAwIC
289 FTAVBAj+1QzaXaN9FwYJKoUDBwECBQEBgAyK54euw0sHhEVEkA0=
290         """)
291         prv_key_our = hexdec("3FC01CDCD4EC5F972EB482774C41E66DB7F380528DFE9E67992BA05AEE462435757530E641077CE587B976C8EEB48C48FD33FD175F0C7DE6A44E014E6BCB074B")[::-1]
292
293         def keker(curve, prv, pub, ukm):
294             return kek_34102012256(
295                 curve,
296                 prv_unmarshal(prv),
297                 pub_unmarshal(pub, mode=2012),
298                 ukm_unmarshal(ukm),
299             )
300
301         self.process_cms(
302             content_info_raw,
303             prv_key_our,
304             "GostR3410_2012_TC26_ParamSetB",
305             keker,
306             b"Test message",
307         )
308
309
310 @skipIf(not pyderasn_exists, "PyDERASN dependency is required")
311 class TestEnvelopedKARI(TestCase):
312     """EnvelopedData KeyAgreeRecipientInfo-based test vectors from
313     "Использование алгоритмов ГОСТ 28147-89, ГОСТ Р 34.11 и ГОСТ Р 34.10
314     в криптографических сообщениях формата CMS" (TK26CMS.pdf)
315     """
316
317     def process_cms(
318             self,
319             content_info_raw,
320             prv_key_our,
321             curve_name,
322             keker,
323             plaintext_expected,
324     ):
325         sbox = "Gost28147_tc26_ParamZ"
326         content_info, tail = ContentInfo().decode(content_info_raw)
327         self.assertSequenceEqual(tail, b"")
328         enveloped_data, tail = EnvelopedData().decode(bytes(content_info["content"]))
329         self.assertSequenceEqual(tail, b"")
330         eci = enveloped_data["encryptedContentInfo"]
331         kari = enveloped_data["recipientInfos"][0]["kari"]
332         pub_key_their, tail = OctetString().decode(
333             bytes(kari["originator"]["originatorKey"]["publicKey"]),
334         )
335         self.assertSequenceEqual(tail, b"")
336         ukm = bytes(kari["ukm"])
337         rek = kari["recipientEncryptedKeys"][0]
338         curve = GOST3410Curve(*CURVE_PARAMS[curve_name])
339         kek = keker(curve, prv_key_our, bytes(pub_key_their), ukm)
340         encrypted_key, tail = Gost2814789EncryptedKey().decode(
341             bytes(rek["encryptedKey"]),
342         )
343         self.assertSequenceEqual(tail, b"")
344         key_wrapped = bytes(encrypted_key["encryptedKey"])
345         mac = bytes(encrypted_key["macKey"])
346         cek = unwrap_gost(kek, ukm + key_wrapped + mac, sbox=sbox)
347         ciphertext = bytes(eci["encryptedContent"])
348         encryption_params, tail = Gost2814789Parameters().decode(
349             bytes(eci["contentEncryptionAlgorithm"]["parameters"])
350         )
351         self.assertSequenceEqual(tail, b"")
352         iv = bytes(encryption_params["iv"])
353         self.assertSequenceEqual(
354             cfb_decrypt(cek, ciphertext, iv, sbox=sbox, mesh=True),
355             plaintext_expected,
356         )
357
358     def test_256(self):
359         content_info_raw = b64decode("""
360 MIIBhgYJKoZIhvcNAQcDoIIBdzCCAXMCAQIxggEwoYIBLAIBA6BooWYwHwYIKoUD
361 BwEBAQEwEwYHKoUDAgIkAAYIKoUDBwEBAgIDQwAEQPAdWM4pO38iZ49UjaXQpq+a
362 jhTa4KwY4B9TFMK7AiYmbFKE0eX/wvu69kFMQ2o3OJTnMOlr1WHiPYOmNO6C5hOh
363 CgQIX+vNomZakEIwIgYIKoUDBwEBAQEwFgYHKoUDAgINADALBgkqhQMHAQIFAQEw
364 gYwwgYkwWzBWMSkwJwYJKoZIhvcNAQkBFhpHb3N0UjM0MTAtMjAxMkBleGFtcGxl
365 LmNvbTEpMCcGA1UEAxMgR29zdFIzNDEwLTIwMTIgMjU2IGJpdHMgZXhjaGFuZ2UC
366 AQEEKjAoBCCNhrZOr7x2fsjjQAeDMv/tSoNRQSSQzzxgqdnYxJ3fIAQEgYLqVDA6
367 BgkqhkiG9w0BBwEwHwYGKoUDAgIVMBUECHVmR/S+hlYiBgkqhQMHAQIFAQGADEI9
368 UNjyuY+54uVcHw==
369         """)
370         prv_key_our = hexdec("BFCF1D623E5CDD3032A7C6EABB4A923C46E43D640FFEAAF2C3ED39A8FA399924")[::-1]
371
372         def keker(curve, prv, pub, ukm):
373             return kek_34102012256(
374                 curve,
375                 prv_unmarshal(prv),
376                 pub_unmarshal(pub),
377                 ukm_unmarshal(ukm),
378                 mode=2001,
379             )
380
381         self.process_cms(
382             content_info_raw,
383             prv_key_our,
384             "GostR3410_2001_CryptoPro_XchA_ParamSet",
385             keker,
386             b"Test message",
387         )
388
389     def test_512(self):
390         content_info_raw = b64decode("""
391 MIIBzAYJKoZIhvcNAQcDoIIBvTCCAbkCAQIxggF2oYIBcgIBA6CBraGBqjAhBggq
392 hQMHAQEBAjAVBgkqhQMHAQIBAgIGCCqFAwcBAQIDA4GEAASBgCB0nQy/Ljva/mRj
393 w6o+eDKIvnxwYIQB5XCHhZhCpHNZiWcFxFpYXZLWRPKifOxV7NStvqGE1+fkfhBe
394 btkQu0tdC1XL3LO2Cp/jX16XhW/IP5rKV84qWr1Owy/6tnSsNRb+ez6IttwVvaVV
395 pA6ONFy9p9gawoC8nitvAVJkWW0PoQoECDVfxzxgMTAHMCIGCCqFAwcBAQECMBYG
396 ByqFAwICDQAwCwYJKoUDBwECBQEBMIGMMIGJMFswVjEpMCcGCSqGSIb3DQEJARYa
397 R29zdFIzNDEwLTIwMTJAZXhhbXBsZS5jb20xKTAnBgNVBAMTIEdvc3RSMzQxMC0y
398 MDEyIDUxMiBiaXRzIGV4Y2hhbmdlAgEBBCowKAQg8C/OcxRR0Uq8nDjHrQlayFb3
399 WFUZEnEuAKcuG6dTOawEBLhi9hIwOgYJKoZIhvcNAQcBMB8GBiqFAwICFTAVBAiD
400 1wH+CX6CwgYJKoUDBwECBQEBgAzUvQI4H2zRfgNgdlY=
401         """)
402         prv_key_our = hexdec("3FC01CDCD4EC5F972EB482774C41E66DB7F380528DFE9E67992BA05AEE462435757530E641077CE587B976C8EEB48C48FD33FD175F0C7DE6A44E014E6BCB074B")[::-1]
403
404         def keker(curve, prv, pub, ukm):
405             return kek_34102012256(
406                 curve,
407                 prv_unmarshal(prv),
408                 pub_unmarshal(pub, mode=2012),
409                 ukm_unmarshal(ukm),
410             )
411
412         self.process_cms(
413             content_info_raw,
414             prv_key_our,
415             "GostR3410_2012_TC26_ParamSetB",
416             keker,
417             b"Test message",
418         )