]> Cypherpunks.ru repositories - pygost.git/blob - pygost/test_x509.py
Remove excess mode kwargs from gost3410* functions
[pygost.git] / pygost / test_x509.py
1 # coding: utf-8
2 # PyGOST -- Pure Python GOST cryptographic functions library
3 # Copyright (C) 2015-2020 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, version 3 of the License.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 from base64 import b64decode
18 from unittest import skipIf
19 from unittest import TestCase
20
21 from pygost.gost3410 import CURVES
22 from pygost.gost3410 import prv_unmarshal
23 from pygost.gost3410 import pub_marshal
24 from pygost.gost3410 import pub_unmarshal
25 from pygost.gost3410 import public_key
26 from pygost.gost3410 import verify
27 from pygost.gost34112012256 import GOST34112012256
28 from pygost.gost34112012512 import GOST34112012512
29 from pygost.utils import hexdec
30
31 try:
32
33     from pyderasn import Any
34     from pyderasn import BitString
35     from pyderasn import Boolean
36     from pyderasn import GeneralizedTime
37     from pyderasn import Integer
38     from pyderasn import OctetString
39     from pyderasn import PrintableString
40     from pyderasn import UTCTime
41
42     from pygost.asn1schemas.oids import id_at_commonName
43     from pygost.asn1schemas.oids import id_ce_basicConstraints
44     from pygost.asn1schemas.oids import id_GostR3410_2001_TestParamSet
45     from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256
46     from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256_paramSetA
47     from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512
48     from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512_paramSetTest
49     from pygost.asn1schemas.oids import id_tc26_gost3411_2012_256
50     from pygost.asn1schemas.oids import id_tc26_signwithdigest_gost3410_2012_256
51     from pygost.asn1schemas.oids import id_tc26_signwithdigest_gost3410_2012_512
52     from pygost.asn1schemas.pkcs10 import Attributes
53     from pygost.asn1schemas.pkcs10 import CertificationRequest
54     from pygost.asn1schemas.pkcs10 import CertificationRequestInfo
55     from pygost.asn1schemas.x509 import AlgorithmIdentifier
56     from pygost.asn1schemas.x509 import AttributeType
57     from pygost.asn1schemas.x509 import AttributeTypeAndValue
58     from pygost.asn1schemas.x509 import AttributeValue
59     from pygost.asn1schemas.x509 import BasicConstraints
60     from pygost.asn1schemas.x509 import Certificate
61     from pygost.asn1schemas.x509 import CertificateList
62     from pygost.asn1schemas.x509 import CertificateSerialNumber
63     from pygost.asn1schemas.x509 import Extension
64     from pygost.asn1schemas.x509 import Extensions
65     from pygost.asn1schemas.x509 import GostR34102012PublicKeyParameters
66     from pygost.asn1schemas.x509 import Name
67     from pygost.asn1schemas.x509 import RDNSequence
68     from pygost.asn1schemas.x509 import RelativeDistinguishedName
69     from pygost.asn1schemas.x509 import SubjectPublicKeyInfo
70     from pygost.asn1schemas.x509 import TBSCertificate
71     from pygost.asn1schemas.x509 import TBSCertList
72     from pygost.asn1schemas.x509 import Time
73     from pygost.asn1schemas.x509 import Validity
74     from pygost.asn1schemas.x509 import Version
75
76 except ImportError:
77     pyderasn_exists = False
78 else:
79     pyderasn_exists = True
80
81
82 @skipIf(not pyderasn_exists, "PyDERASN dependency is required")
83 class TestCertificate(TestCase):
84     """Certificate test vectors from "Использования алгоритмов ГОСТ Р
85     34.10, ГОСТ Р 34.11 в профиле сертификата и списке отзыва
86     сертификатов (CRL) инфраструктуры открытых ключей X.509"
87     (TK26IOK.pdf)
88     """
89
90     def process_cert(self, curve_name, hasher, prv_key_raw, cert_raw):
91         cert, tail = Certificate().decode(cert_raw, ctx={
92             "defines_by_path": (
93                 (
94                     (
95                         "tbsCertificate",
96                         "subjectPublicKeyInfo",
97                         "algorithm",
98                         "algorithm",
99                     ),
100                     (
101                         (
102                             ("..", "subjectPublicKey"),
103                             {
104                                 id_tc26_gost3410_2012_256: OctetString(),
105                                 id_tc26_gost3410_2012_512: OctetString(),
106                             },
107                         ),
108                     ),
109                 ),
110             ),
111         })
112         self.assertSequenceEqual(tail, b"")
113         curve = CURVES[curve_name]
114         prv_key = prv_unmarshal(prv_key_raw)
115         spk = cert["tbsCertificate"]["subjectPublicKeyInfo"]["subjectPublicKey"]
116         self.assertIsNotNone(spk.defined)
117         _, pub_key_raw = spk.defined
118         pub_key = pub_unmarshal(bytes(pub_key_raw))
119         self.assertSequenceEqual(pub_key, public_key(curve, prv_key))
120         self.assertTrue(verify(
121             curve,
122             pub_key,
123             hasher(cert["tbsCertificate"].encode()).digest()[::-1],
124             bytes(cert["signatureValue"]),
125         ))
126
127     def test_256(self):
128         cert_raw = b64decode("""
129 MIICYjCCAg+gAwIBAgIBATAKBggqhQMHAQEDAjBWMSkwJwYJKoZIhvcNAQkBFhpH
130 b3N0UjM0MTAtMjAxMkBleGFtcGxlLmNvbTEpMCcGA1UEAxMgR29zdFIzNDEwLTIw
131 MTIgKDI1NiBiaXQpIGV4YW1wbGUwHhcNMTMxMTA1MTQwMjM3WhcNMzAxMTAxMTQw
132 MjM3WjBWMSkwJwYJKoZIhvcNAQkBFhpHb3N0UjM0MTAtMjAxMkBleGFtcGxlLmNv
133 bTEpMCcGA1UEAxMgR29zdFIzNDEwLTIwMTIgKDI1NiBiaXQpIGV4YW1wbGUwZjAf
134 BggqhQMHAQEBATATBgcqhQMCAiQABggqhQMHAQECAgNDAARAut/Qw1MUq9KPqkdH
135 C2xAF3K7TugHfo9n525D2s5mFZdD5pwf90/i4vF0mFmr9nfRwMYP4o0Pg1mOn5Rl
136 aXNYraOBwDCBvTAdBgNVHQ4EFgQU1fIeN1HaPbw+XWUzbkJ+kHJUT0AwCwYDVR0P
137 BAQDAgHGMA8GA1UdEwQIMAYBAf8CAQEwfgYDVR0BBHcwdYAU1fIeN1HaPbw+XWUz
138 bkJ+kHJUT0ChWqRYMFYxKTAnBgkqhkiG9w0BCQEWGkdvc3RSMzQxMC0yMDEyQGV4
139 YW1wbGUuY29tMSkwJwYDVQQDEyBHb3N0UjM0MTAtMjAxMiAoMjU2IGJpdCkgZXhh
140 bXBsZYIBATAKBggqhQMHAQEDAgNBAF5bm4BbARR6hJLEoWJkOsYV3Hd7kXQQjz3C
141 dqQfmHrz6TI6Xojdh/t8ckODv/587NS5/6KsM77vc6Wh90NAT2s=
142         """)
143         prv_key_raw = hexdec("BFCF1D623E5CDD3032A7C6EABB4A923C46E43D640FFEAAF2C3ED39A8FA399924")[::-1]
144         self.process_cert(
145             "id-GostR3410-2001-CryptoPro-XchA-ParamSet",
146             GOST34112012256,
147             prv_key_raw,
148             cert_raw,
149         )
150
151     def test_512(self):
152         cert_raw = b64decode("""
153 MIIC6DCCAlSgAwIBAgIBATAKBggqhQMHAQEDAzBWMSkwJwYJKoZIhvcNAQkBFhpH
154 b3N0UjM0MTAtMjAxMkBleGFtcGxlLmNvbTEpMCcGA1UEAxMgR29zdFIzNDEwLTIw
155 MTIgKDUxMiBiaXQpIGV4YW1wbGUwHhcNMTMxMDA0MDczNjA0WhcNMzAxMDAxMDcz
156 NjA0WjBWMSkwJwYJKoZIhvcNAQkBFhpHb3N0UjM0MTAtMjAxMkBleGFtcGxlLmNv
157 bTEpMCcGA1UEAxMgR29zdFIzNDEwLTIwMTIgKDUxMiBiaXQpIGV4YW1wbGUwgaow
158 IQYIKoUDBwEBAQIwFQYJKoUDBwECAQICBggqhQMHAQECAwOBhAAEgYATGQ9VCiM5
159 FRGCQ8MEz2F1dANqhaEuywa8CbxOnTvaGJpFQVXQwkwvLFAKh7hk542vOEtxpKtT
160 CXfGf84nRhMH/Q9bZeAc2eO/yhxrsQhTBufa1Fuou2oe/jUOaG6RAtUUvRzhNTpp
161 RGGl1+EIY2vzzUua9j9Ol/gAoy/LNKQIfqOBwDCBvTAdBgNVHQ4EFgQUPcbTRXJZ
162 nHtjj+eBP7b5lcTMekIwCwYDVR0PBAQDAgHGMA8GA1UdEwQIMAYBAf8CAQEwfgYD
163 VR0BBHcwdYAUPcbTRXJZnHtjj+eBP7b5lcTMekKhWqRYMFYxKTAnBgkqhkiG9w0B
164 CQEWGkdvc3RSMzQxMC0yMDEyQGV4YW1wbGUuY29tMSkwJwYDVQQDEyBHb3N0UjM0
165 MTAtMjAxMiAoNTEyIGJpdCkgZXhhbXBsZYIBATAKBggqhQMHAQEDAwOBgQBObS7o
166 ppPTXzHyVR1DtPa8b57nudJzI4czhsfeX5HDntOq45t9B/qSs8dC6eGxbhHZ9zCO
167 SFtxWYdmg0au8XI9Xb8vTC1qdwWID7FFjMWDNQZb6lYh/J+8F2xKylvB5nIlRZqO
168 o3eUNFkNyHJwQCk2WoOlO16zwGk2tdKH4KmD5w==
169         """)
170         prv_key_raw = hexdec("3FC01CDCD4EC5F972EB482774C41E66DB7F380528DFE9E67992BA05AEE462435757530E641077CE587B976C8EEB48C48FD33FD175F0C7DE6A44E014E6BCB074B")[::-1]
171         self.process_cert(
172             "id-tc26-gost-3410-12-512-paramSetB",
173             GOST34112012512,
174             prv_key_raw,
175             cert_raw,
176         )
177
178
179 @skipIf(not pyderasn_exists, "PyDERASN dependency is required")
180 class TestRFC4491bis(TestCase):
181     """Test vectors from https://tools.ietf.org/html/draft-deremin-rfc4491-bis-02
182     """
183
184     def _test_vector(
185             self,
186             curve_name,
187             hsh,
188             ai_spki,
189             ai_sign,
190             cert_serial,
191             prv_hex,
192             cr_sign_hex,
193             cr_b64,
194             c_sign_hex,
195             c_b64,
196             crl_sign_hex,
197             crl_b64,
198     ):
199         prv_raw = hexdec(prv_hex)[::-1]
200         prv = prv_unmarshal(prv_raw)
201         curve = CURVES[curve_name]
202         pub = public_key(curve, prv)
203         pub_raw = pub_marshal(pub)
204         subj = Name(("rdnSequence", RDNSequence([
205             RelativeDistinguishedName((
206                 AttributeTypeAndValue((
207                     ("type", AttributeType(id_at_commonName)),
208                     ("value", AttributeValue(PrintableString("Example"))),
209                 )),
210             ))
211         ])))
212         spki = SubjectPublicKeyInfo((
213             ("algorithm", ai_spki),
214             ("subjectPublicKey", BitString(OctetString(pub_raw).encode())),
215         ))
216
217         # Certification request
218         cri = CertificationRequestInfo((
219             ("version", Integer(0)),
220             ("subject", subj),
221             ("subjectPKInfo", spki),
222             ("attributes", Attributes()),
223         ))
224         sign = hexdec(cr_sign_hex)
225         self.assertTrue(verify(
226             curve,
227             pub,
228             hsh(cri.encode()).digest()[::-1],
229             sign,
230         ))
231         cr = CertificationRequest((
232             ("certificationRequestInfo", cri),
233             ("signatureAlgorithm", ai_sign),
234             ("signature", BitString(sign)),
235         ))
236         self.assertSequenceEqual(cr.encode(), b64decode(cr_b64))
237
238         # Certificate
239         tbs = TBSCertificate((
240             ("version", Version("v3")),
241             ("serialNumber", CertificateSerialNumber(cert_serial)),
242             ("signature", ai_sign),
243             ("issuer", subj),
244             ("validity", Validity((
245                 ("notBefore", Time(("utcTime", UTCTime(b"010101000000Z")))),
246                 ("notAfter", Time(("generalTime", GeneralizedTime(b"20501231000000Z")))),
247             ))),
248             ("subject", subj),
249             ("subjectPublicKeyInfo", spki),
250             ("extensions", Extensions((
251                 Extension((
252                     ("extnID", id_ce_basicConstraints),
253                     ("critical", Boolean(True)),
254                     ("extnValue", OctetString(
255                         BasicConstraints((("cA", Boolean(True)),)).encode()
256                     )),
257                 )),
258             ))),
259         ))
260         sign = hexdec(c_sign_hex)
261         self.assertTrue(verify(
262             curve,
263             pub,
264             hsh(tbs.encode()).digest()[::-1],
265             sign,
266         ))
267         cert = Certificate((
268             ("tbsCertificate", tbs),
269             ("signatureAlgorithm", ai_sign),
270             ("signatureValue", BitString(sign)),
271         ))
272         self.assertSequenceEqual(cert.encode(), b64decode(c_b64))
273
274         # CRL
275         tbs = TBSCertList((
276             ("version", Version("v2")),
277             ("signature", ai_sign),
278             ("issuer", subj),
279             ("thisUpdate", Time(("utcTime", UTCTime(b"140101000000Z")))),
280             ("nextUpdate", Time(("utcTime", UTCTime(b"140102000000Z")))),
281         ))
282         sign = hexdec(crl_sign_hex)
283         self.assertTrue(verify(
284             curve,
285             pub,
286             hsh(tbs.encode()).digest()[::-1],
287             sign,
288         ))
289         crl = CertificateList((
290             ("tbsCertList", tbs),
291             ("signatureAlgorithm", ai_sign),
292             ("signatureValue", BitString(sign)),
293         ))
294         self.assertSequenceEqual(crl.encode(), b64decode(crl_b64))
295
296     def test_256_test_paramset(self):
297         self._test_vector(
298             "id-GostR3410-2001-TestParamSet",
299             GOST34112012256,
300             AlgorithmIdentifier((
301                 ("algorithm", id_tc26_gost3410_2012_256),
302                 ("parameters", Any(
303                     GostR34102012PublicKeyParameters((
304                         ("publicKeyParamSet", id_GostR3410_2001_TestParamSet),
305                         ("digestParamSet", id_tc26_gost3411_2012_256),
306                     ))
307                 )),
308             )),
309             AlgorithmIdentifier((
310                 ("algorithm", id_tc26_signwithdigest_gost3410_2012_256),
311             )),
312             10,
313             "7A929ADE789BB9BE10ED359DD39A72C11B60961F49397EEE1D19CE9891EC3B28",
314             "6AAAB38E35D4AAA517940301799122D855484F579F4CBB96D63CDFDF3ACC432A41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493",
315             """
316 MIHTMIGBAgEAMBIxEDAOBgNVBAMTB0V4YW1wbGUwZjAfBggqhQMHAQEBATATBgcq
317 hQMCAiMABggqhQMHAQECAgNDAARAC9hv5djbiWaPeJtOHbqFhcVQi0XsW1nYkG3b
318 cOJJK3/ad/+HGhD73ydm0pPF0WSvuzx7lzpByIXRHXDWibTxJqAAMAoGCCqFAwcB
319 AQMCA0EAaqqzjjXUqqUXlAMBeZEi2FVIT1efTLuW1jzf3zrMQypBqijS8asUgoDN
320 ntVv7aQZdAU1VKQnZ7g60EP9OdwEkw==
321             """,
322             "4D53F012FE081776507D4D9BB81F00EFDB4EEFD4AB83BAC4BACF735173CFA81C41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493",
323             """
324 MIIBLTCB26ADAgECAgEKMAoGCCqFAwcBAQMCMBIxEDAOBgNVBAMTB0V4YW1wbGUw
325 IBcNMDEwMTAxMDAwMDAwWhgPMjA1MDEyMzEwMDAwMDBaMBIxEDAOBgNVBAMTB0V4
326 YW1wbGUwZjAfBggqhQMHAQEBATATBgcqhQMCAiMABggqhQMHAQECAgNDAARAC9hv
327 5djbiWaPeJtOHbqFhcVQi0XsW1nYkG3bcOJJK3/ad/+HGhD73ydm0pPF0WSvuzx7
328 lzpByIXRHXDWibTxJqMTMBEwDwYDVR0TAQH/BAUwAwEB/zAKBggqhQMHAQEDAgNB
329 AE1T8BL+CBd2UH1Nm7gfAO/bTu/Uq4O6xLrPc1Fzz6gcQaoo0vGrFIKAzZ7Vb+2k
330 GXQFNVSkJ2e4OtBD/TncBJM=
331             """,
332             "42BF392A14D3EBE957AF3E46CB50BF5F4221A003AD3D172753C94A9C37A31D2041AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493",
333             """
334 MIGSMEECAQEwCgYIKoUDBwEBAwIwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx
335 MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAgNBAEK/OSoU0+vpV68+
336 RstQv19CIaADrT0XJ1PJSpw3ox0gQaoo0vGrFIKAzZ7Vb+2kGXQFNVSkJ2e4OtBD
337 /TncBJM=
338             """,
339         )
340
341     def test_256a_paramset(self):
342         self._test_vector(
343             "id-tc26-gost-3410-2012-256-paramSetA",
344             GOST34112012256,
345             AlgorithmIdentifier((
346                 ("algorithm", id_tc26_gost3410_2012_256),
347                 ("parameters", Any(
348                     GostR34102012PublicKeyParameters((
349                         ("publicKeyParamSet", id_tc26_gost3410_2012_256_paramSetA),
350                     ))
351                 )),
352             )),
353             AlgorithmIdentifier((
354                 ("algorithm", id_tc26_signwithdigest_gost3410_2012_256),
355             )),
356             10,
357             "7A929ADE789BB9BE10ED359DD39A72C11B60961F49397EEE1D19CE9891EC3B28",
358             "1BDC2A1317679B66232F63EA16FF7C64CCAAB9AD855FC6E18091661DB79D48121D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769",
359             """
360 MIHKMHkCAQAwEjEQMA4GA1UEAxMHRXhhbXBsZTBeMBcGCCqFAwcBAQEBMAsGCSqF
361 AwcBAgEBAQNDAARAdCeV1L7ohN3yhQ/sA+o/rxhE4B2dpgtkUJOlXibfw5l49ZbP
362 TU0MbPHRiUPZRJPRa57AoW1RLS4SfMRpGmMY4qAAMAoGCCqFAwcBAQMCA0EAG9wq
363 Exdnm2YjL2PqFv98ZMyqua2FX8bhgJFmHbedSBIdDh2lvjR8bxtSVseurCAK1krH
364 em9bOg4Jcxjnrm7naQ==
365             """,
366             "140B4DA9124B09CB0D5CE928EE874273A310129492EC0E29369E3B791248578C1D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769",
367             """
368 MIIBJTCB06ADAgECAgEKMAoGCCqFAwcBAQMCMBIxEDAOBgNVBAMTB0V4YW1wbGUw
369 IBcNMDEwMTAxMDAwMDAwWhgPMjA1MDEyMzEwMDAwMDBaMBIxEDAOBgNVBAMTB0V4
370 YW1wbGUwXjAXBggqhQMHAQEBATALBgkqhQMHAQIBAQEDQwAEQHQnldS+6ITd8oUP
371 7APqP68YROAdnaYLZFCTpV4m38OZePWWz01NDGzx0YlD2UST0WuewKFtUS0uEnzE
372 aRpjGOKjEzARMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoUDBwEBAwIDQQAUC02pEksJ
373 yw1c6Sjuh0JzoxASlJLsDik2njt5EkhXjB0OHaW+NHxvG1JWx66sIArWSsd6b1s6
374 DglzGOeubudp
375             """,
376             "14BD68087C3B903C7AA28B07FEB2E7BD6FE0963F563267359F5CD8EAB45059AD1D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769",
377             """
378 MIGSMEECAQEwCgYIKoUDBwEBAwIwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx
379 MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAgNBABS9aAh8O5A8eqKL
380 B/6y571v4JY/VjJnNZ9c2Oq0UFmtHQ4dpb40fG8bUlbHrqwgCtZKx3pvWzoOCXMY
381 565u52k=
382             """,
383         )
384
385     def test_512_test_paramset(self):
386         self._test_vector(
387             "id-tc26-gost-3410-2012-512-paramSetTest",
388             GOST34112012512,
389             AlgorithmIdentifier((
390                 ("algorithm", id_tc26_gost3410_2012_512),
391                 ("parameters", Any(
392                     GostR34102012PublicKeyParameters((
393                         ("publicKeyParamSet", id_tc26_gost3410_2012_512_paramSetTest),
394                     ))
395                 )),
396             )),
397             AlgorithmIdentifier((
398                 ("algorithm", id_tc26_signwithdigest_gost3410_2012_512),
399             )),
400             11,
401             "0BA6048AADAE241BA40936D47756D7C93091A0E8514669700EE7508E508B102072E8123B2200A0563322DAD2827E2714A2636B7BFD18AADFC62967821FA18DD4",
402             "433B1D6CE40A51F1E5737EB16AA2C683829A405B9D9127E21260FC9D6AC05D87BF24E26C45278A5C2192A75BA94993ABD6074E7FF1BF03FD2F5397AFA1D945582F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36",
403             """
404 MIIBTzCBvAIBADASMRAwDgYDVQQDEwdFeGFtcGxlMIGgMBcGCCqFAwcBAQECMAsG
405 CSqFAwcBAgECAAOBhAAEgYDh7zDVLGEz3dmdHVxBRVz3302LTJJbvGmvFDPRVlhR
406 Wt0hRoUMMlxbgcEzvmVaqMTUQOe5io1ZSHsMdpa8xV0R7L53NqnsNX/y/TmTH04R
407 TLjNo1knCsfw5/9D2UGUGeph/Sq3f12fY1I9O1CgT2PioM9Rt8E63CFWDwvUDMnH
408 N6AAMAoGCCqFAwcBAQMDA4GBAEM7HWzkClHx5XN+sWqixoOCmkBbnZEn4hJg/J1q
409 wF2HvyTibEUnilwhkqdbqUmTq9YHTn/xvwP9L1OXr6HZRVgvhvpgoIEJGiPdeV4e
410 PGie5RKjyC7g3MJkPHjuqPys01SSVYSGsg8cnsGXyQaZhQJgyTvLzZxcMxfhk0Th
411 c642
412             """,
413             "415703D892F1A5F3F68C4353189A7EE207B80B5631EF9D49529A4D6B542C2CFA15AA2EACF11F470FDE7D954856903C35FD8F955EF300D95C77534A724A0EEE702F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36",
414             """
415 MIIBqjCCARagAwIBAgIBCzAKBggqhQMHAQEDAzASMRAwDgYDVQQDEwdFeGFtcGxl
416 MCAXDTAxMDEwMTAwMDAwMFoYDzIwNTAxMjMxMDAwMDAwWjASMRAwDgYDVQQDEwdF
417 eGFtcGxlMIGgMBcGCCqFAwcBAQECMAsGCSqFAwcBAgECAAOBhAAEgYDh7zDVLGEz
418 3dmdHVxBRVz3302LTJJbvGmvFDPRVlhRWt0hRoUMMlxbgcEzvmVaqMTUQOe5io1Z
419 SHsMdpa8xV0R7L53NqnsNX/y/TmTH04RTLjNo1knCsfw5/9D2UGUGeph/Sq3f12f
420 Y1I9O1CgT2PioM9Rt8E63CFWDwvUDMnHN6MTMBEwDwYDVR0TAQH/BAUwAwEB/zAK
421 BggqhQMHAQEDAwOBgQBBVwPYkvGl8/aMQ1MYmn7iB7gLVjHvnUlSmk1rVCws+hWq
422 LqzxH0cP3n2VSFaQPDX9j5Ve8wDZXHdTSnJKDu5wL4b6YKCBCRoj3XleHjxonuUS
423 o8gu4NzCZDx47qj8rNNUklWEhrIPHJ7Bl8kGmYUCYMk7y82cXDMX4ZNE4XOuNg==
424             """,
425             "3A13FB7AECDB5560EEF6137CFC5DD64691732EBFB3690A1FC0C7E8A4EEEA08307D648D4DC0986C46A87B3FBE4C7AF42EA34359C795954CA39FF3ABBED9051F4D2F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36",
426             """
427 MIHTMEECAQEwCgYIKoUDBwEBAwMwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx
428 MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAwOBgQA6E/t67NtVYO72
429 E3z8XdZGkXMuv7NpCh/Ax+ik7uoIMH1kjU3AmGxGqHs/vkx69C6jQ1nHlZVMo5/z
430 q77ZBR9NL4b6YKCBCRoj3XleHjxonuUSo8gu4NzCZDx47qj8rNNUklWEhrIPHJ7B
431 l8kGmYUCYMk7y82cXDMX4ZNE4XOuNg==
432             """,
433         )