]> Cypherpunks.ru repositories - pygost.git/blob - pygost/test_x509.py
ce7f3ffbe466a8caf4a52d99af77ed458ca1775a
[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, mode, 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), mode=mode)
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             mode=mode,
126         ))
127
128     def test_256(self):
129         cert_raw = b64decode("""
130 MIICYjCCAg+gAwIBAgIBATAKBggqhQMHAQEDAjBWMSkwJwYJKoZIhvcNAQkBFhpH
131 b3N0UjM0MTAtMjAxMkBleGFtcGxlLmNvbTEpMCcGA1UEAxMgR29zdFIzNDEwLTIw
132 MTIgKDI1NiBiaXQpIGV4YW1wbGUwHhcNMTMxMTA1MTQwMjM3WhcNMzAxMTAxMTQw
133 MjM3WjBWMSkwJwYJKoZIhvcNAQkBFhpHb3N0UjM0MTAtMjAxMkBleGFtcGxlLmNv
134 bTEpMCcGA1UEAxMgR29zdFIzNDEwLTIwMTIgKDI1NiBiaXQpIGV4YW1wbGUwZjAf
135 BggqhQMHAQEBATATBgcqhQMCAiQABggqhQMHAQECAgNDAARAut/Qw1MUq9KPqkdH
136 C2xAF3K7TugHfo9n525D2s5mFZdD5pwf90/i4vF0mFmr9nfRwMYP4o0Pg1mOn5Rl
137 aXNYraOBwDCBvTAdBgNVHQ4EFgQU1fIeN1HaPbw+XWUzbkJ+kHJUT0AwCwYDVR0P
138 BAQDAgHGMA8GA1UdEwQIMAYBAf8CAQEwfgYDVR0BBHcwdYAU1fIeN1HaPbw+XWUz
139 bkJ+kHJUT0ChWqRYMFYxKTAnBgkqhkiG9w0BCQEWGkdvc3RSMzQxMC0yMDEyQGV4
140 YW1wbGUuY29tMSkwJwYDVQQDEyBHb3N0UjM0MTAtMjAxMiAoMjU2IGJpdCkgZXhh
141 bXBsZYIBATAKBggqhQMHAQEDAgNBAF5bm4BbARR6hJLEoWJkOsYV3Hd7kXQQjz3C
142 dqQfmHrz6TI6Xojdh/t8ckODv/587NS5/6KsM77vc6Wh90NAT2s=
143         """)
144         prv_key_raw = hexdec("BFCF1D623E5CDD3032A7C6EABB4A923C46E43D640FFEAAF2C3ED39A8FA399924")[::-1]
145         self.process_cert(
146             "id-GostR3410-2001-CryptoPro-XchA-ParamSet",
147             2001,
148             GOST34112012256,
149             prv_key_raw,
150             cert_raw,
151         )
152
153     def test_512(self):
154         cert_raw = b64decode("""
155 MIIC6DCCAlSgAwIBAgIBATAKBggqhQMHAQEDAzBWMSkwJwYJKoZIhvcNAQkBFhpH
156 b3N0UjM0MTAtMjAxMkBleGFtcGxlLmNvbTEpMCcGA1UEAxMgR29zdFIzNDEwLTIw
157 MTIgKDUxMiBiaXQpIGV4YW1wbGUwHhcNMTMxMDA0MDczNjA0WhcNMzAxMDAxMDcz
158 NjA0WjBWMSkwJwYJKoZIhvcNAQkBFhpHb3N0UjM0MTAtMjAxMkBleGFtcGxlLmNv
159 bTEpMCcGA1UEAxMgR29zdFIzNDEwLTIwMTIgKDUxMiBiaXQpIGV4YW1wbGUwgaow
160 IQYIKoUDBwEBAQIwFQYJKoUDBwECAQICBggqhQMHAQECAwOBhAAEgYATGQ9VCiM5
161 FRGCQ8MEz2F1dANqhaEuywa8CbxOnTvaGJpFQVXQwkwvLFAKh7hk542vOEtxpKtT
162 CXfGf84nRhMH/Q9bZeAc2eO/yhxrsQhTBufa1Fuou2oe/jUOaG6RAtUUvRzhNTpp
163 RGGl1+EIY2vzzUua9j9Ol/gAoy/LNKQIfqOBwDCBvTAdBgNVHQ4EFgQUPcbTRXJZ
164 nHtjj+eBP7b5lcTMekIwCwYDVR0PBAQDAgHGMA8GA1UdEwQIMAYBAf8CAQEwfgYD
165 VR0BBHcwdYAUPcbTRXJZnHtjj+eBP7b5lcTMekKhWqRYMFYxKTAnBgkqhkiG9w0B
166 CQEWGkdvc3RSMzQxMC0yMDEyQGV4YW1wbGUuY29tMSkwJwYDVQQDEyBHb3N0UjM0
167 MTAtMjAxMiAoNTEyIGJpdCkgZXhhbXBsZYIBATAKBggqhQMHAQEDAwOBgQBObS7o
168 ppPTXzHyVR1DtPa8b57nudJzI4czhsfeX5HDntOq45t9B/qSs8dC6eGxbhHZ9zCO
169 SFtxWYdmg0au8XI9Xb8vTC1qdwWID7FFjMWDNQZb6lYh/J+8F2xKylvB5nIlRZqO
170 o3eUNFkNyHJwQCk2WoOlO16zwGk2tdKH4KmD5w==
171         """)
172         prv_key_raw = hexdec("3FC01CDCD4EC5F972EB482774C41E66DB7F380528DFE9E67992BA05AEE462435757530E641077CE587B976C8EEB48C48FD33FD175F0C7DE6A44E014E6BCB074B")[::-1]
173         self.process_cert(
174             "id-tc26-gost-3410-12-512-paramSetB",
175             2012,
176             GOST34112012512,
177             prv_key_raw,
178             cert_raw,
179         )
180
181
182 @skipIf(not pyderasn_exists, "PyDERASN dependency is required")
183 class TestRFC4491bis(TestCase):
184     """Test vectors from https://tools.ietf.org/html/draft-deremin-rfc4491-bis-02
185     """
186
187     def _test_vector(
188             self,
189             curve_name,
190             mode,
191             hsh,
192             ai_spki,
193             ai_sign,
194             cert_serial,
195             prv_hex,
196             cr_sign_hex,
197             cr_b64,
198             c_sign_hex,
199             c_b64,
200             crl_sign_hex,
201             crl_b64,
202     ):
203         prv_raw = hexdec(prv_hex)[::-1]
204         prv = prv_unmarshal(prv_raw)
205         curve = CURVES[curve_name]
206         pub = public_key(curve, prv)
207         pub_raw = pub_marshal(pub, mode=mode)
208         subj = Name(("rdnSequence", RDNSequence([
209             RelativeDistinguishedName((
210                 AttributeTypeAndValue((
211                     ("type", AttributeType(id_at_commonName)),
212                     ("value", AttributeValue(PrintableString("Example"))),
213                 )),
214             ))
215         ])))
216         spki = SubjectPublicKeyInfo((
217             ("algorithm", ai_spki),
218             ("subjectPublicKey", BitString(OctetString(pub_raw).encode())),
219         ))
220
221         # Certification request
222         cri = CertificationRequestInfo((
223             ("version", Integer(0)),
224             ("subject", subj),
225             ("subjectPKInfo", spki),
226             ("attributes", Attributes()),
227         ))
228         sign = hexdec(cr_sign_hex)
229         self.assertTrue(verify(
230             curve,
231             pub,
232             hsh(cri.encode()).digest()[::-1],
233             sign,
234             mode=mode,
235         ))
236         cr = CertificationRequest((
237             ("certificationRequestInfo", cri),
238             ("signatureAlgorithm", ai_sign),
239             ("signature", BitString(sign)),
240         ))
241         self.assertSequenceEqual(cr.encode(), b64decode(cr_b64))
242
243         # Certificate
244         tbs = TBSCertificate((
245             ("version", Version("v3")),
246             ("serialNumber", CertificateSerialNumber(cert_serial)),
247             ("signature", ai_sign),
248             ("issuer", subj),
249             ("validity", Validity((
250                 ("notBefore", Time(("utcTime", UTCTime(b"010101000000Z")))),
251                 ("notAfter", Time(("generalTime", GeneralizedTime(b"20501231000000Z")))),
252             ))),
253             ("subject", subj),
254             ("subjectPublicKeyInfo", spki),
255             ("extensions", Extensions((
256                 Extension((
257                     ("extnID", id_ce_basicConstraints),
258                     ("critical", Boolean(True)),
259                     ("extnValue", OctetString(
260                         BasicConstraints((("cA", Boolean(True)),)).encode()
261                     )),
262                 )),
263             ))),
264         ))
265         sign = hexdec(c_sign_hex)
266         self.assertTrue(verify(
267             curve,
268             pub,
269             hsh(tbs.encode()).digest()[::-1],
270             sign,
271             mode=mode,
272         ))
273         cert = Certificate((
274             ("tbsCertificate", tbs),
275             ("signatureAlgorithm", ai_sign),
276             ("signatureValue", BitString(sign)),
277         ))
278         self.assertSequenceEqual(cert.encode(), b64decode(c_b64))
279
280         # CRL
281         tbs = TBSCertList((
282             ("version", Version("v2")),
283             ("signature", ai_sign),
284             ("issuer", subj),
285             ("thisUpdate", Time(("utcTime", UTCTime(b"140101000000Z")))),
286             ("nextUpdate", Time(("utcTime", UTCTime(b"140102000000Z")))),
287         ))
288         sign = hexdec(crl_sign_hex)
289         self.assertTrue(verify(
290             curve,
291             pub,
292             hsh(tbs.encode()).digest()[::-1],
293             sign,
294             mode=mode,
295         ))
296         crl = CertificateList((
297             ("tbsCertList", tbs),
298             ("signatureAlgorithm", ai_sign),
299             ("signatureValue", BitString(sign)),
300         ))
301         self.assertSequenceEqual(crl.encode(), b64decode(crl_b64))
302
303     def test_256_test_paramset(self):
304         self._test_vector(
305             "id-GostR3410-2001-TestParamSet",
306             2001,
307             GOST34112012256,
308             AlgorithmIdentifier((
309                 ("algorithm", id_tc26_gost3410_2012_256),
310                 ("parameters", Any(
311                     GostR34102012PublicKeyParameters((
312                         ("publicKeyParamSet", id_GostR3410_2001_TestParamSet),
313                         ("digestParamSet", id_tc26_gost3411_2012_256),
314                     ))
315                 )),
316             )),
317             AlgorithmIdentifier((
318                 ("algorithm", id_tc26_signwithdigest_gost3410_2012_256),
319             )),
320             10,
321             "7A929ADE789BB9BE10ED359DD39A72C11B60961F49397EEE1D19CE9891EC3B28",
322             "6AAAB38E35D4AAA517940301799122D855484F579F4CBB96D63CDFDF3ACC432A41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493",
323             """
324 MIHTMIGBAgEAMBIxEDAOBgNVBAMTB0V4YW1wbGUwZjAfBggqhQMHAQEBATATBgcq
325 hQMCAiMABggqhQMHAQECAgNDAARAC9hv5djbiWaPeJtOHbqFhcVQi0XsW1nYkG3b
326 cOJJK3/ad/+HGhD73ydm0pPF0WSvuzx7lzpByIXRHXDWibTxJqAAMAoGCCqFAwcB
327 AQMCA0EAaqqzjjXUqqUXlAMBeZEi2FVIT1efTLuW1jzf3zrMQypBqijS8asUgoDN
328 ntVv7aQZdAU1VKQnZ7g60EP9OdwEkw==
329             """,
330             "4D53F012FE081776507D4D9BB81F00EFDB4EEFD4AB83BAC4BACF735173CFA81C41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493",
331             """
332 MIIBLTCB26ADAgECAgEKMAoGCCqFAwcBAQMCMBIxEDAOBgNVBAMTB0V4YW1wbGUw
333 IBcNMDEwMTAxMDAwMDAwWhgPMjA1MDEyMzEwMDAwMDBaMBIxEDAOBgNVBAMTB0V4
334 YW1wbGUwZjAfBggqhQMHAQEBATATBgcqhQMCAiMABggqhQMHAQECAgNDAARAC9hv
335 5djbiWaPeJtOHbqFhcVQi0XsW1nYkG3bcOJJK3/ad/+HGhD73ydm0pPF0WSvuzx7
336 lzpByIXRHXDWibTxJqMTMBEwDwYDVR0TAQH/BAUwAwEB/zAKBggqhQMHAQEDAgNB
337 AE1T8BL+CBd2UH1Nm7gfAO/bTu/Uq4O6xLrPc1Fzz6gcQaoo0vGrFIKAzZ7Vb+2k
338 GXQFNVSkJ2e4OtBD/TncBJM=
339             """,
340             "42BF392A14D3EBE957AF3E46CB50BF5F4221A003AD3D172753C94A9C37A31D2041AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493",
341             """
342 MIGSMEECAQEwCgYIKoUDBwEBAwIwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx
343 MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAgNBAEK/OSoU0+vpV68+
344 RstQv19CIaADrT0XJ1PJSpw3ox0gQaoo0vGrFIKAzZ7Vb+2kGXQFNVSkJ2e4OtBD
345 /TncBJM=
346             """,
347         )
348
349     def test_256a_paramset(self):
350         self._test_vector(
351             "id-tc26-gost-3410-2012-256-paramSetA",
352             2001,
353             GOST34112012256,
354             AlgorithmIdentifier((
355                 ("algorithm", id_tc26_gost3410_2012_256),
356                 ("parameters", Any(
357                     GostR34102012PublicKeyParameters((
358                         ("publicKeyParamSet", id_tc26_gost3410_2012_256_paramSetA),
359                     ))
360                 )),
361             )),
362             AlgorithmIdentifier((
363                 ("algorithm", id_tc26_signwithdigest_gost3410_2012_256),
364             )),
365             10,
366             "7A929ADE789BB9BE10ED359DD39A72C11B60961F49397EEE1D19CE9891EC3B28",
367             "1BDC2A1317679B66232F63EA16FF7C64CCAAB9AD855FC6E18091661DB79D48121D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769",
368             """
369 MIHKMHkCAQAwEjEQMA4GA1UEAxMHRXhhbXBsZTBeMBcGCCqFAwcBAQEBMAsGCSqF
370 AwcBAgEBAQNDAARAdCeV1L7ohN3yhQ/sA+o/rxhE4B2dpgtkUJOlXibfw5l49ZbP
371 TU0MbPHRiUPZRJPRa57AoW1RLS4SfMRpGmMY4qAAMAoGCCqFAwcBAQMCA0EAG9wq
372 Exdnm2YjL2PqFv98ZMyqua2FX8bhgJFmHbedSBIdDh2lvjR8bxtSVseurCAK1krH
373 em9bOg4Jcxjnrm7naQ==
374             """,
375             "140B4DA9124B09CB0D5CE928EE874273A310129492EC0E29369E3B791248578C1D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769",
376             """
377 MIIBJTCB06ADAgECAgEKMAoGCCqFAwcBAQMCMBIxEDAOBgNVBAMTB0V4YW1wbGUw
378 IBcNMDEwMTAxMDAwMDAwWhgPMjA1MDEyMzEwMDAwMDBaMBIxEDAOBgNVBAMTB0V4
379 YW1wbGUwXjAXBggqhQMHAQEBATALBgkqhQMHAQIBAQEDQwAEQHQnldS+6ITd8oUP
380 7APqP68YROAdnaYLZFCTpV4m38OZePWWz01NDGzx0YlD2UST0WuewKFtUS0uEnzE
381 aRpjGOKjEzARMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoUDBwEBAwIDQQAUC02pEksJ
382 yw1c6Sjuh0JzoxASlJLsDik2njt5EkhXjB0OHaW+NHxvG1JWx66sIArWSsd6b1s6
383 DglzGOeubudp
384             """,
385             "14BD68087C3B903C7AA28B07FEB2E7BD6FE0963F563267359F5CD8EAB45059AD1D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769",
386             """
387 MIGSMEECAQEwCgYIKoUDBwEBAwIwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx
388 MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAgNBABS9aAh8O5A8eqKL
389 B/6y571v4JY/VjJnNZ9c2Oq0UFmtHQ4dpb40fG8bUlbHrqwgCtZKx3pvWzoOCXMY
390 565u52k=
391             """,
392         )
393
394     def test_512_test_paramset(self):
395         self._test_vector(
396             "id-tc26-gost-3410-2012-512-paramSetTest",
397             2012,
398             GOST34112012512,
399             AlgorithmIdentifier((
400                 ("algorithm", id_tc26_gost3410_2012_512),
401                 ("parameters", Any(
402                     GostR34102012PublicKeyParameters((
403                         ("publicKeyParamSet", id_tc26_gost3410_2012_512_paramSetTest),
404                     ))
405                 )),
406             )),
407             AlgorithmIdentifier((
408                 ("algorithm", id_tc26_signwithdigest_gost3410_2012_512),
409             )),
410             11,
411             "0BA6048AADAE241BA40936D47756D7C93091A0E8514669700EE7508E508B102072E8123B2200A0563322DAD2827E2714A2636B7BFD18AADFC62967821FA18DD4",
412             "433B1D6CE40A51F1E5737EB16AA2C683829A405B9D9127E21260FC9D6AC05D87BF24E26C45278A5C2192A75BA94993ABD6074E7FF1BF03FD2F5397AFA1D945582F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36",
413             """
414 MIIBTzCBvAIBADASMRAwDgYDVQQDEwdFeGFtcGxlMIGgMBcGCCqFAwcBAQECMAsG
415 CSqFAwcBAgECAAOBhAAEgYDh7zDVLGEz3dmdHVxBRVz3302LTJJbvGmvFDPRVlhR
416 Wt0hRoUMMlxbgcEzvmVaqMTUQOe5io1ZSHsMdpa8xV0R7L53NqnsNX/y/TmTH04R
417 TLjNo1knCsfw5/9D2UGUGeph/Sq3f12fY1I9O1CgT2PioM9Rt8E63CFWDwvUDMnH
418 N6AAMAoGCCqFAwcBAQMDA4GBAEM7HWzkClHx5XN+sWqixoOCmkBbnZEn4hJg/J1q
419 wF2HvyTibEUnilwhkqdbqUmTq9YHTn/xvwP9L1OXr6HZRVgvhvpgoIEJGiPdeV4e
420 PGie5RKjyC7g3MJkPHjuqPys01SSVYSGsg8cnsGXyQaZhQJgyTvLzZxcMxfhk0Th
421 c642
422             """,
423             "415703D892F1A5F3F68C4353189A7EE207B80B5631EF9D49529A4D6B542C2CFA15AA2EACF11F470FDE7D954856903C35FD8F955EF300D95C77534A724A0EEE702F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36",
424             """
425 MIIBqjCCARagAwIBAgIBCzAKBggqhQMHAQEDAzASMRAwDgYDVQQDEwdFeGFtcGxl
426 MCAXDTAxMDEwMTAwMDAwMFoYDzIwNTAxMjMxMDAwMDAwWjASMRAwDgYDVQQDEwdF
427 eGFtcGxlMIGgMBcGCCqFAwcBAQECMAsGCSqFAwcBAgECAAOBhAAEgYDh7zDVLGEz
428 3dmdHVxBRVz3302LTJJbvGmvFDPRVlhRWt0hRoUMMlxbgcEzvmVaqMTUQOe5io1Z
429 SHsMdpa8xV0R7L53NqnsNX/y/TmTH04RTLjNo1knCsfw5/9D2UGUGeph/Sq3f12f
430 Y1I9O1CgT2PioM9Rt8E63CFWDwvUDMnHN6MTMBEwDwYDVR0TAQH/BAUwAwEB/zAK
431 BggqhQMHAQEDAwOBgQBBVwPYkvGl8/aMQ1MYmn7iB7gLVjHvnUlSmk1rVCws+hWq
432 LqzxH0cP3n2VSFaQPDX9j5Ve8wDZXHdTSnJKDu5wL4b6YKCBCRoj3XleHjxonuUS
433 o8gu4NzCZDx47qj8rNNUklWEhrIPHJ7Bl8kGmYUCYMk7y82cXDMX4ZNE4XOuNg==
434             """,
435             "3A13FB7AECDB5560EEF6137CFC5DD64691732EBFB3690A1FC0C7E8A4EEEA08307D648D4DC0986C46A87B3FBE4C7AF42EA34359C795954CA39FF3ABBED9051F4D2F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36",
436             """
437 MIHTMEECAQEwCgYIKoUDBwEBAwMwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx
438 MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAwOBgQA6E/t67NtVYO72
439 E3z8XdZGkXMuv7NpCh/Ax+ik7uoIMH1kjU3AmGxGqHs/vkx69C6jQ1nHlZVMo5/z
440 q77ZBR9NL4b6YKCBCRoj3XleHjxonuUSo8gu4NzCZDx47qj8rNNUklWEhrIPHJ7B
441 l8kGmYUCYMk7y82cXDMX4ZNE4XOuNg==
442             """,
443         )