2 # PyGOST -- Pure Python GOST cryptographic functions library
3 # Copyright (C) 2015-2020 Sergey Matveev <stargrave@stargrave.org>
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.
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.
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/>.
17 from base64 import b64decode
18 from unittest import skipIf
19 from unittest import TestCase
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
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
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
77 pyderasn_exists = False
79 pyderasn_exists = True
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"
90 def process_cert(self, curve_name, hasher, prv_key_raw, cert_raw):
91 cert, tail = Certificate().decode(cert_raw, ctx={
96 "subjectPublicKeyInfo",
102 ("..", "subjectPublicKey"),
104 id_tc26_gost3410_2012_256: OctetString(),
105 id_tc26_gost3410_2012_512: OctetString(),
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(
123 hasher(cert["tbsCertificate"].encode()).digest()[::-1],
124 bytes(cert["signatureValue"]),
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=
143 prv_key_raw = hexdec("BFCF1D623E5CDD3032A7C6EABB4A923C46E43D640FFEAAF2C3ED39A8FA399924")[::-1]
145 "id-GostR3410-2001-CryptoPro-XchA-ParamSet",
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==
170 prv_key_raw = hexdec("3FC01CDCD4EC5F972EB482774C41E66DB7F380528DFE9E67992BA05AEE462435757530E641077CE587B976C8EEB48C48FD33FD175F0C7DE6A44E014E6BCB074B")[::-1]
172 "id-tc26-gost-3410-12-512-paramSetB",
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
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"))),
212 spki = SubjectPublicKeyInfo((
213 ("algorithm", ai_spki),
214 ("subjectPublicKey", BitString(OctetString(pub_raw).encode())),
217 # Certification request
218 cri = CertificationRequestInfo((
219 ("version", Integer(0)),
221 ("subjectPKInfo", spki),
222 ("attributes", Attributes()),
224 sign = hexdec(cr_sign_hex)
225 self.assertTrue(verify(
228 hsh(cri.encode()).digest()[::-1],
231 cr = CertificationRequest((
232 ("certificationRequestInfo", cri),
233 ("signatureAlgorithm", ai_sign),
234 ("signature", BitString(sign)),
236 self.assertSequenceEqual(cr.encode(), b64decode(cr_b64))
239 tbs = TBSCertificate((
240 ("version", Version("v3")),
241 ("serialNumber", CertificateSerialNumber(cert_serial)),
242 ("signature", ai_sign),
244 ("validity", Validity((
245 ("notBefore", Time(("utcTime", UTCTime(b"010101000000Z")))),
246 ("notAfter", Time(("generalTime", GeneralizedTime(b"20501231000000Z")))),
249 ("subjectPublicKeyInfo", spki),
250 ("extensions", Extensions((
252 ("extnID", id_ce_basicConstraints),
253 ("critical", Boolean(True)),
254 ("extnValue", OctetString(
255 BasicConstraints((("cA", Boolean(True)),)).encode()
260 sign = hexdec(c_sign_hex)
261 self.assertTrue(verify(
264 hsh(tbs.encode()).digest()[::-1],
268 ("tbsCertificate", tbs),
269 ("signatureAlgorithm", ai_sign),
270 ("signatureValue", BitString(sign)),
272 self.assertSequenceEqual(cert.encode(), b64decode(c_b64))
276 ("version", Version("v2")),
277 ("signature", ai_sign),
279 ("thisUpdate", Time(("utcTime", UTCTime(b"140101000000Z")))),
280 ("nextUpdate", Time(("utcTime", UTCTime(b"140102000000Z")))),
282 sign = hexdec(crl_sign_hex)
283 self.assertTrue(verify(
286 hsh(tbs.encode()).digest()[::-1],
289 crl = CertificateList((
290 ("tbsCertList", tbs),
291 ("signatureAlgorithm", ai_sign),
292 ("signatureValue", BitString(sign)),
294 self.assertSequenceEqual(crl.encode(), b64decode(crl_b64))
296 def test_256_test_paramset(self):
298 "id-GostR3410-2001-TestParamSet",
300 AlgorithmIdentifier((
301 ("algorithm", id_tc26_gost3410_2012_256),
303 GostR34102012PublicKeyParameters((
304 ("publicKeyParamSet", id_GostR3410_2001_TestParamSet),
305 ("digestParamSet", id_tc26_gost3411_2012_256),
309 AlgorithmIdentifier((
310 ("algorithm", id_tc26_signwithdigest_gost3410_2012_256),
313 "7A929ADE789BB9BE10ED359DD39A72C11B60961F49397EEE1D19CE9891EC3B28",
314 "6AAAB38E35D4AAA517940301799122D855484F579F4CBB96D63CDFDF3ACC432A41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493",
316 MIHTMIGBAgEAMBIxEDAOBgNVBAMTB0V4YW1wbGUwZjAfBggqhQMHAQEBATATBgcq
317 hQMCAiMABggqhQMHAQECAgNDAARAC9hv5djbiWaPeJtOHbqFhcVQi0XsW1nYkG3b
318 cOJJK3/ad/+HGhD73ydm0pPF0WSvuzx7lzpByIXRHXDWibTxJqAAMAoGCCqFAwcB
319 AQMCA0EAaqqzjjXUqqUXlAMBeZEi2FVIT1efTLuW1jzf3zrMQypBqijS8asUgoDN
320 ntVv7aQZdAU1VKQnZ7g60EP9OdwEkw==
322 "4D53F012FE081776507D4D9BB81F00EFDB4EEFD4AB83BAC4BACF735173CFA81C41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493",
324 MIIBLTCB26ADAgECAgEKMAoGCCqFAwcBAQMCMBIxEDAOBgNVBAMTB0V4YW1wbGUw
325 IBcNMDEwMTAxMDAwMDAwWhgPMjA1MDEyMzEwMDAwMDBaMBIxEDAOBgNVBAMTB0V4
326 YW1wbGUwZjAfBggqhQMHAQEBATATBgcqhQMCAiMABggqhQMHAQECAgNDAARAC9hv
327 5djbiWaPeJtOHbqFhcVQi0XsW1nYkG3bcOJJK3/ad/+HGhD73ydm0pPF0WSvuzx7
328 lzpByIXRHXDWibTxJqMTMBEwDwYDVR0TAQH/BAUwAwEB/zAKBggqhQMHAQEDAgNB
329 AE1T8BL+CBd2UH1Nm7gfAO/bTu/Uq4O6xLrPc1Fzz6gcQaoo0vGrFIKAzZ7Vb+2k
330 GXQFNVSkJ2e4OtBD/TncBJM=
332 "42BF392A14D3EBE957AF3E46CB50BF5F4221A003AD3D172753C94A9C37A31D2041AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493",
334 MIGSMEECAQEwCgYIKoUDBwEBAwIwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx
335 MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAgNBAEK/OSoU0+vpV68+
336 RstQv19CIaADrT0XJ1PJSpw3ox0gQaoo0vGrFIKAzZ7Vb+2kGXQFNVSkJ2e4OtBD
341 def test_256a_paramset(self):
343 "id-tc26-gost-3410-2012-256-paramSetA",
345 AlgorithmIdentifier((
346 ("algorithm", id_tc26_gost3410_2012_256),
348 GostR34102012PublicKeyParameters((
349 ("publicKeyParamSet", id_tc26_gost3410_2012_256_paramSetA),
353 AlgorithmIdentifier((
354 ("algorithm", id_tc26_signwithdigest_gost3410_2012_256),
357 "7A929ADE789BB9BE10ED359DD39A72C11B60961F49397EEE1D19CE9891EC3B28",
358 "1BDC2A1317679B66232F63EA16FF7C64CCAAB9AD855FC6E18091661DB79D48121D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769",
360 MIHKMHkCAQAwEjEQMA4GA1UEAxMHRXhhbXBsZTBeMBcGCCqFAwcBAQEBMAsGCSqF
361 AwcBAgEBAQNDAARAdCeV1L7ohN3yhQ/sA+o/rxhE4B2dpgtkUJOlXibfw5l49ZbP
362 TU0MbPHRiUPZRJPRa57AoW1RLS4SfMRpGmMY4qAAMAoGCCqFAwcBAQMCA0EAG9wq
363 Exdnm2YjL2PqFv98ZMyqua2FX8bhgJFmHbedSBIdDh2lvjR8bxtSVseurCAK1krH
366 "140B4DA9124B09CB0D5CE928EE874273A310129492EC0E29369E3B791248578C1D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769",
368 MIIBJTCB06ADAgECAgEKMAoGCCqFAwcBAQMCMBIxEDAOBgNVBAMTB0V4YW1wbGUw
369 IBcNMDEwMTAxMDAwMDAwWhgPMjA1MDEyMzEwMDAwMDBaMBIxEDAOBgNVBAMTB0V4
370 YW1wbGUwXjAXBggqhQMHAQEBATALBgkqhQMHAQIBAQEDQwAEQHQnldS+6ITd8oUP
371 7APqP68YROAdnaYLZFCTpV4m38OZePWWz01NDGzx0YlD2UST0WuewKFtUS0uEnzE
372 aRpjGOKjEzARMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoUDBwEBAwIDQQAUC02pEksJ
373 yw1c6Sjuh0JzoxASlJLsDik2njt5EkhXjB0OHaW+NHxvG1JWx66sIArWSsd6b1s6
376 "14BD68087C3B903C7AA28B07FEB2E7BD6FE0963F563267359F5CD8EAB45059AD1D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769",
378 MIGSMEECAQEwCgYIKoUDBwEBAwIwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx
379 MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAgNBABS9aAh8O5A8eqKL
380 B/6y571v4JY/VjJnNZ9c2Oq0UFmtHQ4dpb40fG8bUlbHrqwgCtZKx3pvWzoOCXMY
385 def test_512_test_paramset(self):
387 "id-tc26-gost-3410-2012-512-paramSetTest",
389 AlgorithmIdentifier((
390 ("algorithm", id_tc26_gost3410_2012_512),
392 GostR34102012PublicKeyParameters((
393 ("publicKeyParamSet", id_tc26_gost3410_2012_512_paramSetTest),
397 AlgorithmIdentifier((
398 ("algorithm", id_tc26_signwithdigest_gost3410_2012_512),
401 "0BA6048AADAE241BA40936D47756D7C93091A0E8514669700EE7508E508B102072E8123B2200A0563322DAD2827E2714A2636B7BFD18AADFC62967821FA18DD4",
402 "433B1D6CE40A51F1E5737EB16AA2C683829A405B9D9127E21260FC9D6AC05D87BF24E26C45278A5C2192A75BA94993ABD6074E7FF1BF03FD2F5397AFA1D945582F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36",
404 MIIBTzCBvAIBADASMRAwDgYDVQQDEwdFeGFtcGxlMIGgMBcGCCqFAwcBAQECMAsG
405 CSqFAwcBAgECAAOBhAAEgYDh7zDVLGEz3dmdHVxBRVz3302LTJJbvGmvFDPRVlhR
406 Wt0hRoUMMlxbgcEzvmVaqMTUQOe5io1ZSHsMdpa8xV0R7L53NqnsNX/y/TmTH04R
407 TLjNo1knCsfw5/9D2UGUGeph/Sq3f12fY1I9O1CgT2PioM9Rt8E63CFWDwvUDMnH
408 N6AAMAoGCCqFAwcBAQMDA4GBAEM7HWzkClHx5XN+sWqixoOCmkBbnZEn4hJg/J1q
409 wF2HvyTibEUnilwhkqdbqUmTq9YHTn/xvwP9L1OXr6HZRVgvhvpgoIEJGiPdeV4e
410 PGie5RKjyC7g3MJkPHjuqPys01SSVYSGsg8cnsGXyQaZhQJgyTvLzZxcMxfhk0Th
413 "415703D892F1A5F3F68C4353189A7EE207B80B5631EF9D49529A4D6B542C2CFA15AA2EACF11F470FDE7D954856903C35FD8F955EF300D95C77534A724A0EEE702F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36",
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==
425 "3A13FB7AECDB5560EEF6137CFC5DD64691732EBFB3690A1FC0C7E8A4EEEA08307D648D4DC0986C46A87B3FBE4C7AF42EA34359C795954CA39FF3ABBED9051F4D2F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36",
427 MIHTMEECAQEwCgYIKoUDBwEBAwMwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx
428 MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAwOBgQA6E/t67NtVYO72
429 E3z8XdZGkXMuv7NpCh/Ax+ik7uoIMH1kjU3AmGxGqHs/vkx69C6jQ1nHlZVMo5/z
430 q77ZBR9NL4b6YKCBCRoj3XleHjxonuUSo8gu4NzCZDx47qj8rNNUklWEhrIPHJ7B
431 l8kGmYUCYMk7y82cXDMX4ZNE4XOuNg==