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, mode, 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), mode=mode)
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"]),
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=
144 prv_key_raw = hexdec("BFCF1D623E5CDD3032A7C6EABB4A923C46E43D640FFEAAF2C3ED39A8FA399924")[::-1]
146 "id-GostR3410-2001-CryptoPro-XchA-ParamSet",
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==
172 prv_key_raw = hexdec("3FC01CDCD4EC5F972EB482774C41E66DB7F380528DFE9E67992BA05AEE462435757530E641077CE587B976C8EEB48C48FD33FD175F0C7DE6A44E014E6BCB074B")[::-1]
174 "id-tc26-gost-3410-12-512-paramSetB",
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
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"))),
216 spki = SubjectPublicKeyInfo((
217 ("algorithm", ai_spki),
218 ("subjectPublicKey", BitString(OctetString(pub_raw).encode())),
221 # Certification request
222 cri = CertificationRequestInfo((
223 ("version", Integer(0)),
225 ("subjectPKInfo", spki),
226 ("attributes", Attributes()),
228 sign = hexdec(cr_sign_hex)
229 self.assertTrue(verify(
232 hsh(cri.encode()).digest()[::-1],
236 cr = CertificationRequest((
237 ("certificationRequestInfo", cri),
238 ("signatureAlgorithm", ai_sign),
239 ("signature", BitString(sign)),
241 self.assertSequenceEqual(cr.encode(), b64decode(cr_b64))
244 tbs = TBSCertificate((
245 ("version", Version("v3")),
246 ("serialNumber", CertificateSerialNumber(cert_serial)),
247 ("signature", ai_sign),
249 ("validity", Validity((
250 ("notBefore", Time(("utcTime", UTCTime(b"010101000000Z")))),
251 ("notAfter", Time(("generalTime", GeneralizedTime(b"20501231000000Z")))),
254 ("subjectPublicKeyInfo", spki),
255 ("extensions", Extensions((
257 ("extnID", id_ce_basicConstraints),
258 ("critical", Boolean(True)),
259 ("extnValue", OctetString(
260 BasicConstraints((("cA", Boolean(True)),)).encode()
265 sign = hexdec(c_sign_hex)
266 self.assertTrue(verify(
269 hsh(tbs.encode()).digest()[::-1],
274 ("tbsCertificate", tbs),
275 ("signatureAlgorithm", ai_sign),
276 ("signatureValue", BitString(sign)),
278 open("/tmp/1", "wb").write(cert.encode())
279 self.assertSequenceEqual(cert.encode(), b64decode(c_b64))
283 ("version", Version("v2")),
284 ("signature", ai_sign),
286 ("thisUpdate", Time(("utcTime", UTCTime(b"140101000000Z")))),
287 ("nextUpdate", Time(("utcTime", UTCTime(b"140102000000Z")))),
289 sign = hexdec(crl_sign_hex)
290 self.assertTrue(verify(
293 hsh(tbs.encode()).digest()[::-1],
297 crl = CertificateList((
298 ("tbsCertList", tbs),
299 ("signatureAlgorithm", ai_sign),
300 ("signatureValue", BitString(sign)),
302 self.assertSequenceEqual(crl.encode(), b64decode(crl_b64))
304 def test_256_test_paramset(self):
306 "id-GostR3410-2001-TestParamSet",
309 AlgorithmIdentifier((
310 ("algorithm", id_tc26_gost3410_2012_256),
312 GostR34102012PublicKeyParameters((
313 ("publicKeyParamSet", id_GostR3410_2001_TestParamSet),
314 ("digestParamSet", id_tc26_gost3411_2012_256),
318 AlgorithmIdentifier((
319 ("algorithm", id_tc26_signwithdigest_gost3410_2012_256),
322 "7A929ADE789BB9BE10ED359DD39A72C11B60961F49397EEE1D19CE9891EC3B28",
323 "6AAAB38E35D4AAA517940301799122D855484F579F4CBB96D63CDFDF3ACC432A41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493",
325 MIHTMIGBAgEAMBIxEDAOBgNVBAMTB0V4YW1wbGUwZjAfBggqhQMHAQEBATATBgcq
326 hQMCAiMABggqhQMHAQECAgNDAARAC9hv5djbiWaPeJtOHbqFhcVQi0XsW1nYkG3b
327 cOJJK3/ad/+HGhD73ydm0pPF0WSvuzx7lzpByIXRHXDWibTxJqAAMAoGCCqFAwcB
328 AQMCA0EAaqqzjjXUqqUXlAMBeZEi2FVIT1efTLuW1jzf3zrMQypBqijS8asUgoDN
329 ntVv7aQZdAU1VKQnZ7g60EP9OdwEkw==
331 "4D53F012FE081776507D4D9BB81F00EFDB4EEFD4AB83BAC4BACF735173CFA81C41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493",
333 MIIBLTCB26ADAgECAgEKMAoGCCqFAwcBAQMCMBIxEDAOBgNVBAMTB0V4YW1wbGUw
334 IBcNMDEwMTAxMDAwMDAwWhgPMjA1MDEyMzEwMDAwMDBaMBIxEDAOBgNVBAMTB0V4
335 YW1wbGUwZjAfBggqhQMHAQEBATATBgcqhQMCAiMABggqhQMHAQECAgNDAARAC9hv
336 5djbiWaPeJtOHbqFhcVQi0XsW1nYkG3bcOJJK3/ad/+HGhD73ydm0pPF0WSvuzx7
337 lzpByIXRHXDWibTxJqMTMBEwDwYDVR0TAQH/BAUwAwEB/zAKBggqhQMHAQEDAgNB
338 AE1T8BL+CBd2UH1Nm7gfAO/bTu/Uq4O6xLrPc1Fzz6gcQaoo0vGrFIKAzZ7Vb+2k
339 GXQFNVSkJ2e4OtBD/TncBJM=
341 "42BF392A14D3EBE957AF3E46CB50BF5F4221A003AD3D172753C94A9C37A31D2041AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493",
343 MIGSMEECAQEwCgYIKoUDBwEBAwIwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx
344 MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAgNBAEK/OSoU0+vpV68+
345 RstQv19CIaADrT0XJ1PJSpw3ox0gQaoo0vGrFIKAzZ7Vb+2kGXQFNVSkJ2e4OtBD
350 def test_256a_paramset(self):
352 "id-tc26-gost-3410-2012-256-paramSetA",
355 AlgorithmIdentifier((
356 ("algorithm", id_tc26_gost3410_2012_256),
358 GostR34102012PublicKeyParameters((
359 ("publicKeyParamSet", id_tc26_gost3410_2012_256_paramSetA),
363 AlgorithmIdentifier((
364 ("algorithm", id_tc26_signwithdigest_gost3410_2012_256),
367 "7A929ADE789BB9BE10ED359DD39A72C11B60961F49397EEE1D19CE9891EC3B28",
368 "1BDC2A1317679B66232F63EA16FF7C64CCAAB9AD855FC6E18091661DB79D48121D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769",
370 MIHKMHkCAQAwEjEQMA4GA1UEAxMHRXhhbXBsZTBeMBcGCCqFAwcBAQEBMAsGCSqF
371 AwcBAgEBAQNDAARAdCeV1L7ohN3yhQ/sA+o/rxhE4B2dpgtkUJOlXibfw5l49ZbP
372 TU0MbPHRiUPZRJPRa57AoW1RLS4SfMRpGmMY4qAAMAoGCCqFAwcBAQMCA0EAG9wq
373 Exdnm2YjL2PqFv98ZMyqua2FX8bhgJFmHbedSBIdDh2lvjR8bxtSVseurCAK1krH
376 "140B4DA9124B09CB0D5CE928EE874273A310129492EC0E29369E3B791248578C1D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769",
378 MIIBJTCB06ADAgECAgEKMAoGCCqFAwcBAQMCMBIxEDAOBgNVBAMTB0V4YW1wbGUw
379 IBcNMDEwMTAxMDAwMDAwWhgPMjA1MDEyMzEwMDAwMDBaMBIxEDAOBgNVBAMTB0V4
380 YW1wbGUwXjAXBggqhQMHAQEBATALBgkqhQMHAQIBAQEDQwAEQHQnldS+6ITd8oUP
381 7APqP68YROAdnaYLZFCTpV4m38OZePWWz01NDGzx0YlD2UST0WuewKFtUS0uEnzE
382 aRpjGOKjEzARMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoUDBwEBAwIDQQAUC02pEksJ
383 yw1c6Sjuh0JzoxASlJLsDik2njt5EkhXjB0OHaW+NHxvG1JWx66sIArWSsd6b1s6
386 "14BD68087C3B903C7AA28B07FEB2E7BD6FE0963F563267359F5CD8EAB45059AD1D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769",
388 MIGSMEECAQEwCgYIKoUDBwEBAwIwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx
389 MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAgNBABS9aAh8O5A8eqKL
390 B/6y571v4JY/VjJnNZ9c2Oq0UFmtHQ4dpb40fG8bUlbHrqwgCtZKx3pvWzoOCXMY
395 def test_512_test_paramset(self):
397 "id-tc26-gost-3410-2012-512-paramSetTest",
400 AlgorithmIdentifier((
401 ("algorithm", id_tc26_gost3410_2012_512),
403 GostR34102012PublicKeyParameters((
404 ("publicKeyParamSet", id_tc26_gost3410_2012_512_paramSetTest),
408 AlgorithmIdentifier((
409 ("algorithm", id_tc26_signwithdigest_gost3410_2012_512),
412 "0BA6048AADAE241BA40936D47756D7C93091A0E8514669700EE7508E508B102072E8123B2200A0563322DAD2827E2714A2636B7BFD18AADFC62967821FA18DD4",
413 "433B1D6CE40A51F1E5737EB16AA2C683829A405B9D9127E21260FC9D6AC05D87BF24E26C45278A5C2192A75BA94993ABD6074E7FF1BF03FD2F5397AFA1D945582F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36",
415 MIIBTzCBvAIBADASMRAwDgYDVQQDEwdFeGFtcGxlMIGgMBcGCCqFAwcBAQECMAsG
416 CSqFAwcBAgECAAOBhAAEgYDh7zDVLGEz3dmdHVxBRVz3302LTJJbvGmvFDPRVlhR
417 Wt0hRoUMMlxbgcEzvmVaqMTUQOe5io1ZSHsMdpa8xV0R7L53NqnsNX/y/TmTH04R
418 TLjNo1knCsfw5/9D2UGUGeph/Sq3f12fY1I9O1CgT2PioM9Rt8E63CFWDwvUDMnH
419 N6AAMAoGCCqFAwcBAQMDA4GBAEM7HWzkClHx5XN+sWqixoOCmkBbnZEn4hJg/J1q
420 wF2HvyTibEUnilwhkqdbqUmTq9YHTn/xvwP9L1OXr6HZRVgvhvpgoIEJGiPdeV4e
421 PGie5RKjyC7g3MJkPHjuqPys01SSVYSGsg8cnsGXyQaZhQJgyTvLzZxcMxfhk0Th
424 "415703D892F1A5F3F68C4353189A7EE207B80B5631EF9D49529A4D6B542C2CFA15AA2EACF11F470FDE7D954856903C35FD8F955EF300D95C77534A724A0EEE702F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36",
426 MIIBqjCCARagAwIBAgIBCzAKBggqhQMHAQEDAzASMRAwDgYDVQQDEwdFeGFtcGxl
427 MCAXDTAxMDEwMTAwMDAwMFoYDzIwNTAxMjMxMDAwMDAwWjASMRAwDgYDVQQDEwdF
428 eGFtcGxlMIGgMBcGCCqFAwcBAQECMAsGCSqFAwcBAgECAAOBhAAEgYDh7zDVLGEz
429 3dmdHVxBRVz3302LTJJbvGmvFDPRVlhRWt0hRoUMMlxbgcEzvmVaqMTUQOe5io1Z
430 SHsMdpa8xV0R7L53NqnsNX/y/TmTH04RTLjNo1knCsfw5/9D2UGUGeph/Sq3f12f
431 Y1I9O1CgT2PioM9Rt8E63CFWDwvUDMnHN6MTMBEwDwYDVR0TAQH/BAUwAwEB/zAK
432 BggqhQMHAQEDAwOBgQBBVwPYkvGl8/aMQ1MYmn7iB7gLVjHvnUlSmk1rVCws+hWq
433 LqzxH0cP3n2VSFaQPDX9j5Ve8wDZXHdTSnJKDu5wL4b6YKCBCRoj3XleHjxonuUS
434 o8gu4NzCZDx47qj8rNNUklWEhrIPHJ7Bl8kGmYUCYMk7y82cXDMX4ZNE4XOuNg==
436 "3A13FB7AECDB5560EEF6137CFC5DD64691732EBFB3690A1FC0C7E8A4EEEA08307D648D4DC0986C46A87B3FBE4C7AF42EA34359C795954CA39FF3ABBED9051F4D2F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36",
438 MIHTMEECAQEwCgYIKoUDBwEBAwMwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx
439 MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAwOBgQA6E/t67NtVYO72
440 E3z8XdZGkXMuv7NpCh/Ax+ik7uoIMH1kjU3AmGxGqHs/vkx69C6jQ1nHlZVMo5/z
441 q77ZBR9NL4b6YKCBCRoj3XleHjxonuUSo8gu4NzCZDx47qj8rNNUklWEhrIPHJ7B
442 l8kGmYUCYMk7y82cXDMX4ZNE4XOuNg==